Discussion:
P0135R1, copy elision and constant class objects
(too old to reply)
Andrzej Krzemieński
2016-07-08 11:38:00 UTC
Permalink
Hi Everyone,
It is my understanding that in the following direct initialization, where
the destination object is const T and source object is (non-const) T, copy
elision is disallowed:

T make_T();

const T t = make_T();
Right?

Does P0135R1 (Wording for guaranteed copy elision through simplified value
categories) change this? Or do we still require a move constructor to be
invoked in such case?

Regards,
&rzej;
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2016-07-08 13:06:27 UTC
Permalink
Post by Andrzej Krzemieński
Hi Everyone,
It is my understanding that in the following direct initialization, where
the destination object is const T and source object is (non-const) T, copy
What "direct initialization" are you talking about? The initialization of
the `const T t` is *copy* initialization
<http://en.cppreference.com/w/cpp/language/copy_initialization>. As
evidenced by the fact that you use an `=` sign. I highly doubt that
guaranteed elision will transform copy initialization into direct
initialization.

I think your question is whether initializing a const-qualified `T` permits
guaranteed elision. I'm pretty sure that initializing a const-qualified `T`
from a prvalue is a case for *non-*guaranteed elision, so I see no reason
why they would add specialized wording that didn't allow it to be
guaranteed.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Andrzej Krzemieński
2016-07-08 13:23:31 UTC
Permalink
Post by Nicol Bolas
Post by Andrzej Krzemieński
Hi Everyone,
It is my understanding that in the following direct initialization, where
the destination object is const T and source object is (non-const) T, copy
What "direct initialization" are you talking about? The initialization of
the `const T t` is *copy* initialization
<http://en.cppreference.com/w/cpp/language/copy_initialization>. As
evidenced by the fact that you use an `=` sign. I highly doubt that
guaranteed elision will transform copy initialization into direct
initialization.
My bad; I meant copy-initialization.
Post by Nicol Bolas
I think your question is whether initializing a const-qualified `T`
permits guaranteed elision. I'm pretty sure that initializing a
const-qualified `T` from a prvalue is a case for *non-*guaranteed
elision, so I see no reason why they would add specialized wording that
didn't allow it to be guaranteed.
Sorry, so many negatives, that I did not understand your reply.

It is my understanding that in C++14, compiler must not elide a
copy-initialization of const T, because it might lose observable side
effects of the constructor call: the standard does not allow copy elision
in this case (only the as-if rule). Do you agree with this assertion about
C++14?

Now, about C++17 (and P0135R1), my questions:

1. Is copy elision guaranteed for copy-initialization of const T with T?
2. Is copy elision even allowed (given that the constructor of T might
have side effects)?

According to my interpretation, the answers to both questions are no and
no: We must use a constructor, we must materialize the temporary. But I am
not 100% sure.


Regards,

&rzej;
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2016-07-08 14:55:32 UTC
Permalink
Post by Andrzej Krzemieński
Post by Nicol Bolas
Post by Andrzej Krzemieński
Hi Everyone,
It is my understanding that in the following direct initialization,
where the destination object is const T and source object is (non-const) T,
What "direct initialization" are you talking about? The initialization of
the `const T t` is *copy* initialization
<http://en.cppreference.com/w/cpp/language/copy_initialization>. As
evidenced by the fact that you use an `=` sign. I highly doubt that
guaranteed elision will transform copy initialization into direct
initialization.
My bad; I meant copy-initialization.
Post by Nicol Bolas
I think your question is whether initializing a const-qualified `T`
permits guaranteed elision. I'm pretty sure that initializing a
const-qualified `T` from a prvalue is a case for *non-*guaranteed
elision, so I see no reason why they would add specialized wording that
didn't allow it to be guaranteed.
Sorry, so many negatives, that I did not understand your reply.
It is my understanding that in C++14, compiler must not elide a
copy-initialization of const T, because it might lose observable side
effects of the constructor call: the standard does not allow copy elision
in this case (only the as-if rule).
Technically, *all* copy/move elision could have observable side-effects
that will no longer happen if the compiler elides the copy/move. The
standard is effectively saying under which circumstances that such side
effects cannot be relied upon.

Do you agree with this assertion about C++14?
... Yes, but I was looking at N4582, the most recent C++ draft. This draft
does not include any of P0135 in it, but it does say this:

when a temporary class object that has not been bound to a reference (12.2)
Post by Andrzej Krzemieński
would be copied/moved to a class object with the same type (*ignoring
cv-qualification*), the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted
copy/move
Whereas N4140 says this:

when a temporary class object that has not been bound to a reference (12.2)
Post by Andrzej Krzemieński
would be copied/moved to a class object with *the same cv-unqualified
type*, the copy/move operation can be omitted by constructing the
temporary object directly into the target of the omitted copy/move
So while C++14 does ship as you say, wording changes *preceding* guaranteed
copy elision seem to permit elision in the case of a `const T` being
initialized from a prvalue of type non-const `T`. I couldn't tell you if
this was the result of a defect report or not. But I am sure that it had
nothing to do with copy/move constructor side effects ;)

Note that cppreference.com gets the C++14-and-before wording wrong, using
the post-C++14 wording in all cases.
Post by Andrzej Krzemieński
1. Is copy elision guaranteed for copy-initialization of const T with T?
We don't have P0135R1, but the description from P0135R0 makes it clear
that this ought to be allowed. Basically, P0135 says that prvalues don't
make temporaries; the context in which they are used does. And the list of
contexts which require a temporary does not include initializing a variable
of the same base type with a different cv-qualifier.

So my reading of P0135R0 is that this would be allowed.
Post by Andrzej Krzemieński
1. Is copy elision even allowed (given that the constructor of T might
have side effects)?
As previously stated, yes, regardless of P0135.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
t***@gmail.com
2016-07-08 16:41:01 UTC
Permalink
Post by Nicol Bolas
... Yes, but I was looking at N4582, the most recent C++ draft. This draft
when a temporary class object that has not been bound to a reference
(12.2) would be copied/moved to a class object with the same type (*ignoring
cv-qualification*), the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted
copy/move
when a temporary class object that has not been bound to a reference
(12.2) would be copied/moved to a class object with *the same
cv-unqualified type*, the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted
copy/move
So while C++14 does ship as you say, wording changes *preceding*
guaranteed copy elision seem to permit elision in the case of a `const T`
being initialized from a prvalue of type non-const `T`. I couldn't tell you
if this was the result of a defect report or not. But I am sure that it had
nothing to do with copy/move constructor side effects ;)
Aren't "the same type (ignoring cv-qualification)" and "the same
cv-unqualified type" just 2 ways to express the same thing? Note that the
latter says cv-*unqualified* not cv-qualified.

I just tested g++/clang in c++14 mode and none of them do the copy, I guess
the change in the wording you quoted is not for semantic but for clearness
because people might misread unqualified as qualified.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
T. C.
2016-07-08 19:01:42 UTC
Permalink
Post by t***@gmail.com
Post by Nicol Bolas
... Yes, but I was looking at N4582, the most recent C++ draft. This
when a temporary class object that has not been bound to a reference
(12.2) would be copied/moved to a class object with the same type (*ignoring
cv-qualification*), the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted
copy/move
when a temporary class object that has not been bound to a reference
(12.2) would be copied/moved to a class object with *the same
cv-unqualified type*, the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted
copy/move
So while C++14 does ship as you say, wording changes *preceding*
guaranteed copy elision seem to permit elision in the case of a `const T`
being initialized from a prvalue of type non-const `T`. I couldn't tell you
if this was the result of a defect report or not. But I am sure that it had
nothing to do with copy/move constructor side effects ;)
Aren't "the same type (ignoring cv-qualification)" and "the same
cv-unqualified type" just 2 ways to express the same thing? Note that the
latter says cv-*unqualified* not cv-qualified.
I just tested g++/clang in c++14 mode and none of them do the copy, I
guess the change in the wording you quoted is not for semantic but for
clearness because people might misread unqualified as qualified.
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1916

The previous wording can be misread as requiring both types to be
cv-unqualified.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Loading...