template <class S>class sptr{ S * m_obj; bool m_mine; void release() { if (m_mine) delete m_obj; m_obj=nullptr; } public: sptr (S *const &i=nullptr): m_obj(i), m_mine(false) {} sptr (S *&&i): m_obj(i), m_mine(true) {i=nullptr;} sptr&operator= (S *const &i) { release(); m_obj=i; m_mine=false; return *this; } sptr&operator= (S *&&i): { release(); m_obj=i; i=nullptr; m_mine=true; return *this; } // other stuff, you get the gist ~sptr ( release(); ) };
sptr<S> p_s (new S);
(because new produces an xvalue)
but I can also say
sptr<S> p_s;S s;p_s=&s; // uh-oh
but you can say that that the result of address-of is associated (in a loose sense) with an object -- the object it just took the address of.
It produces a pointer that could theoretically have the delete operator called on it somewhere.
Consider the following:
The result of the address-of operator is not associated with any **pointer** object. In the context of that quote, "object" refers to an object of the same type than the prvalue expression.
You can also call 'delete static_cast<int*>(0);' and clearly 0 is not associated with any object.
You will just need to use a different design for your problem. I could suggest passing a flag indicating ownership, although I don't really believe in "sometimes"-owning smart pointers...
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
2015-02-27 12:32 GMT+01:00 Farid Mehrabi <farid....@gmail.com>:
> but again IMHO result of address operator should be const and so should the
> get member of smart pointers:
It has never been part of the design goals of unique_ptr (or
shared_ptr) to propagate cv-qualifications of the wrapped pointer-like
thingee and accepting your proposal would break existing code.
The address-of operator should produce an rvalue (in the C++11 sense) rather than a prvalue.
Prvalues are rvalues. xvalues are rvalues as well. I don't understand how what you propose wouldsolve your problem. Whatever you do for & will be also valid for new.
> prvalues bind to rvalue-references. Ordinary rvalues do not.
I can not dispute this as the standard does not define the term "ordinary rvalue".
void Foo (int const &);
versus
void Foo (int &&);
Prvalues are rvalues. xvalues are rvalues as well. I don't understand how what you propose wouldsolve your problem. Whatever you do for & will be also valid for new.prvalues bind to rvalue-references. Ordinary rvalues do not.An xvalue (i.e. result of new) should always bind to an rvalue-rerefence.Allowing &x to bind to an rvalue reference implies the pointer thus produced has move semantics, but in actual practice those semantics are never intended by that operator.
--
On Friday, February 27, 2015 at 11:28:11 AM UTC-5, Spencer Simpson wrote:Prvalues are rvalues. xvalues are rvalues as well. I don't understand how what you propose wouldsolve your problem. Whatever you do for & will be also valid for new.prvalues bind to rvalue-references. Ordinary rvalues do not.An xvalue (i.e. result of new) should always bind to an rvalue-rerefence.Allowing &x to bind to an rvalue reference implies the pointer thus produced has move semantics, but in actual practice those semantics are never intended by that operator.
And to me this is the crux of the issue.
What you want to do is to define semantics around the concept of moving vs. copying a pointer. If you take the address of something, you argue that the semantic intent is to copy the pointer, that you're not trying to transfer ownership of the pointer itself.
There are several problems here, syntactically. The first is that the address of operator can be overloaded (unfortunately). Which means that it's up to the overload to decide what to return. And this includes the value category. So there's no way to enforce these semantics globally.
The second is that std::addressof (the only solution if you really want to get the address of an object. Unfortunately) returns the object by value. So it's an xvalue. Which means, under your desired semantics, this would represent moving the object.
So implementing your semantics would require lots of changes. Some of which may not be backwards-compatible.
And personally... I can't say I agree with these semantics to begin with. Consider your code:
ptr_type<T> a = &b;
ptr_type<T> c = new T;
If I know nothing about ptr_type's implementation, my expectation is that both of these do the same thing. I would not expect 'a' and 'c' to be semantically any different. And therefore, if ptr_type is an owning smart pointer, I would very much expect the first line to fail code review, since it clearly says that you're sticking a pointer that can't be deleted into a smart pointer that will try to delete it.
I prefer being explicit about movement myself. If I were to have a smart pointer class that could be owning or non-owning, then I would want that expression to be explicit when it adopts a pointer (or doesn't adopt it). So at the very least, I would want to see something like this:
ptr_type<T> a = {&b, noadopt};
ptr_type<T> c = new T;
That way, it's immediately obvious what's going on. You don't need to know rules about what's a prvalue/xvalue/rvalue. You can read the code and understand what's going on. By default, the pointer is adopted, and if you don't want adoption, you use a different constructor. The deleters for shared_ptr and unique_ptr's are a great way to handle the unowning case.
Don't make the reader of your code have to know esoteric rules about value categories.If & produced an ordinary rvalue rather than a prvalue, it wouldn't bind to an rvalue reference; but new (producing an xvalue) still would.
If you could say that like:ptr_type<T> a = &b;ptr_type<T> c = std::move(new T);it _might_ be more easily understood? And not require a specialized and wordy mylib::noadopt.
If I know nothing about ptr_type's implementation, my expectation is that both of these do the same thing.
I prefer being explicit about movement myself.
Don't make the reader of your code have to know esoteric rules about value categories.
It has never been part of the design goals of unique_ptr (or
shared_ptr) to propagate cv-qualifications of the wrapped pointer-like
thingee and accepting your proposal would break existing code. I
strongly suggest to introduce your own additional layering for these
purposes.
There currently exists a proposal to add such a library component
(albeit restricted to const qualifications) the standard library, see
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4372.html
By the way I am a const-o-phile. It ('const') is good to encourage optimizations,
IMHO facilitating this approach might improve code safety, by preventing a shared_ptr/unique_ptr/smart_ptr from being accidentally initialized with '&x'.
On 28 February 2015 at 18:37, Farid Mehrabi <farid....@gmail.com> wrote:IMHO facilitating this approach might improve code safety, by preventing a shared_ptr/unique_ptr/smart_ptr from being accidentally initialized with '&x'.
I've never seen this done accidentally. I have seen brand new beginners to the language do this deliberately because they didn't understand smart pointers, but education about ownership and lifetime proved far more valuable.
observer_ptr<T> take_address(T& t) { return make_observer(&t); }
int main() {
int i = 42;
observer_ptr<int> obs;
obs = take_address(i); // does this move-assign or copy-assign?
}
const observer_ptr<T> take_address(T& t) { return make_observer(&t); }
T* const operator&(T& t) { ... }
2015-02-28 18:37 GMT+01:00 Farid Mehrabi <farid....@gmail.com>:
>> There currently exists a proposal to add such a library component
>> (albeit restricted to const qualifications) the standard library, see
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4372.html
>>
>
> Good link but my post wasn`t about cv propagation.
OK, I misunderstood your suggestion, I (falsly) assumed that you had a
typo in your code when you suggested to add const to the returned
type.
> The const specifier was
> meant to affect the pointer itself,not the pointed to object.
Can you please elaborate why you the returned pointer value itself
should be const? Especially since C++11 with move semantics I haven't
seen good use-cases to return const prvalues. For non-class types this
const-qualification will be removed during expression analysis anyway.
For class-types it only prevents the move-semantics. Once I get the
value as a non-const value, I still can modify it.
> AFAIK const
> rvalues can`t bind to none const rvalue references.
You are mislead. The language requires that the following code is well-formed:
int const foo() { return 42; }
int&& ri = foo();
int main() {}
It will work for class-types. But for what reasons do you want this property?
>
> where "pointed_cv" refers to cv-qualification of pointed to object while
> 'const' is affecting the [smart] pointer.
> Should I add the full 'template' declarations to disambiguate all the above?
>
> I just re-downloaded http://www.stroustrup.com/terminology.pdf to remember
> the insane meanings of "xpg"s.
What precisely are you meaning by xpg? Assuming you meant xvalues,
prvalues, and glvalues: Why should these meanings be insane?
> So where should the 'const rvalue' be placed
> on the "W"-shaped diagram? Isn`t this an "IM"? what shall we call it?
Why should a const prvalue something different than a prvalue?
> Still
> there are IMHO large gaps between the language constructs and theoretical
> terms.
Sorry, I fail to see these gaps in regard to value categories.
> By the way I am a const-o-phile. It ('const') is good to encourage
> optimizations, good to prevent unintended modifications, ...
Well, const has some good reasons, but it seems to me that your
suggestion does not belong to one of those.
I fail to see what kind of "code-safety" your suggestions would bring
to the C++ community.
- Daniel
significant change than you originally suggested. Also likely one with
serious compatibility issues.)
>> Why should a const prvalue something different than a prvalue?
>
> the 'const' qualifier is supposed to prevent modifications - including
> moving from - the rvalue that is already lacking identity. By striping it
> of its mobility, it falls completely out of the diagram.
Well, it doesn't, and the const qualifier here doesn't mean anything and
is *ignored entirely* by compilers.
On 2015-03-03 15:00, Farid Mehrabi wrote:
> 2015-02-28 21:55 GMT+03:30 Daniel Krügler wrote:
>> You are mislead. The language requires that the following code is
>> well-formed:
>>
>> int const foo() { return 42; }
>>
>> int&& ri = foo();
>>
>> int main() {}
>>
>> It will work for class-types. But for what reasons do you want this
>> property?
>
> It is but why should it be well-formed?
...because the 'const' is meaningless in that context.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
On Wed, Mar 04, 2015 at 09:42:06PM +0330, Farid Mehrabi wrote:
> Just one question: why should a library programmer pay the extra typing
> time to qualify a return type as 'const' while he dose not really mean that
> the result is supposed to be const?
The thread did have a reference to "naïve programmers (who) have been
incorrectly marking return values as 'const'" that fell away in Mathhew's
answer.
The reasoning could be that adding const to object return values prevents
mutating operations on the returned temporaries and having them on the
non-object return values will then be consistent and can't harm anything.
> regards,
> FM.
>
> 2015-03-04 19:37 GMT+03:30 Matthew Woehlke <mw_t...@users.sourceforge.net>:
>
> > On 2015-03-03 18:21, Magnus Fromreide wrote:
> > > On Tue, Mar 03, 2015 at 05:27:58PM -0500, Matthew Woehlke wrote:
> > >> Currently [marking POD return values 'const'] means nothing.
> > >
> > > It actually do mean something - annoyance and trouble.
> > >
> > > Consider a library with many current clients and declarations like the
> > > following one:
> > >
> > > struct foo_base {
> > > virtual const int bar();
> > > };
> > >
> > > In this case removing the 'const' in the base class will trigger
> > compilation
> > > failures in the clients and that makes a gradual migration away from the
> > > unnecessary const version harder.
> >
> > Hmm... Okay, the const doesn't mean anything *else*. That said, I'd
> > almost consider it a defect that override resolution considers a
> > meaningless token.
> >
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
On 2015-03-04 21:09, Thiago Macieira wrote:
> On Wednesday 04 March 2015 18:27:21 Matthew Woehlke wrote:
>> Still, either GCC is non-conforming (seems unlikely), or the standard
>> allows the compiler to disregard the 'const'. If the latter case, to me
>> that says that having a const POD return type is dubious if not outright
>> dangerous, regardless of what some particular compiler does. (If the
>> standard allows it to be ignored, what's to stop a compiler from
>> changing its behavior in some future release?)
>
> I thought we were talking about virtual overrides differing in the constness.
That was elsewhere in the thread :-).
> TBH, I don't know about this particular scenario. PODs and non-PODs differ in
> behaviour as to what you can do to their rvalues:
>
> template <typename T> T returnIt();
> template <typename T> void modifyIt1() { returnIt<T>() = T{}; }
>
> int main()
> {
> // compiles:
> modifyIt2(returnIt<const int>());
That... is very surprising. It does NOT compile if the return type is
not templated, i.e.:
const int test();
void mutate() { test() = 0; } // nope; error
> }
>
> In one case, you can modify an rvalue POD but not the rvalue non-POD; in the
> other, you can modify the rvalue non-POD but can't the rvalue POD.
>
> If GCC's implementation is non-conforming, then so is Clang's and ICC's. But
> it would make sense if they were and the third case above weren't allowed: no
> binding of a const prvalue to a non-const rvalue, regardless of PODness.
Do you mean that you think the third case compiling is an error? (If
yes, I would be rather inclined to agree.) I can't think of a good
reason why this should be allowed... I *could* argue that the template
case should allow the assignment regardless, for the sake of generic
programming, but it already doesn't because the non-const doesn't allow
the assignment either. It actually feels quite bizarre that the const
would *allow* assignment while the non-const does not.
(I have more sympathy for eliding the -Wignored-qualifiers diagnostic
here, since it would be somewhat obnoxious to avoid it in the template
case.)
I guess I can understand allowing modification of a non-POD rvalue,
since that could potentially have side effects (e.g. in operator=, or if
the destructor behaves differently depending on the value).
--
Matthew