 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
glenlow@pixelglow.com Guest
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Tue Aug 02, 2005 8:30 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
In article <1122964657.782608.4270 (AT) z14g2000cwz (DOT) googlegroups.com>,
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | 1. Is the N1377, N1690 etc. proposal already accepted for inclusion in
C++0x?
|
No.
At the Spring '05 meeting the proposed wording in N1770 was forwarded
from the evolution working group to the core working group. This is a
very significant milestone towards standardization. I am presently
cautiously optimistic that this functionality will make it into C++0X.
The evolution working group expressed some concern with how the syntax
might interact with other proposals before this working group. However
no conflicts or problems are currently known to exist. There is simply
concern since this small change has a very large ripple effect
throughout the language. So I am somewhat less optimistic that N1770
will be standardized with the exact syntax proposed.
On the library side, the library working group gave a tentative nod
towards N1771 and requested more detailed proposals complete with
proposed wording. I am currently working on those papers and hope to
have many (all?) ready for the Fall '05 meeting.
-Howard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Mirek Fidler Guest
|
Posted: Tue Aug 02, 2005 11:17 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
| Quote: | very significant milestone towards standardization. I am presently
cautiously optimistic that this functionality will make it into C++0X.
|
Can I honestly ask about the composition issue?
struct C {
Foo a; // has standard Foo(const Foo&) constructor
Bar a; // has both standard and move constructor
};
What kinds of constructor will C have?
I know I should be able to find it in the proposal, but at the moment my
research was not able to give me results. Means I am still hoping :)
BTW, if my worst worries are proven to be true (C has just standard
constructor), I attempt to foretell that this will be immediate
problem... (yes, I know there is a little that can be done at this moment).
Mirek
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gabriel Dos Reis Guest
|
Posted: Wed Aug 03, 2005 9:55 am Post subject: Re: Rvalue references -- a done deal? |
|
|
Howard Hinnant <hinnant (AT) metrowerks (DOT) com> writes:
| Quote: | In article <1122964657.782608.4270 (AT) z14g2000cwz (DOT) googlegroups.com>,
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
1. Is the N1377, N1690 etc. proposal already accepted for inclusion in
C++0x?
No.
At the Spring '05 meeting the proposed wording in N1770 was forwarded
from the evolution working group to the core working group. This is a
very significant milestone towards standardization. I am presently
cautiously optimistic that this functionality will make it into C++0X.
The evolution working group expressed some concern with how the syntax
might interact with other proposals before this working group. However
no conflicts or problems are currently known to exist.
|
Sine I happen to be part of the people who expressed concerns about the
syntax, I guess I must speak up. From my perspective, the syntax to
say when an "rvalue reference" is preferred or not happens to sit in a
very crowed area, from syntax perspective. Given other proposals to
add user-defined literals and improvements of initialization, I
consider that a global, "unified" vision is needed.
--
Gabriel Dos Reis
[email]gdr (AT) integrable-solutions (DOT) net[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joe Gottman Guest
|
Posted: Wed Aug 03, 2005 9:59 am Post subject: Re: Rvalue references -- a done deal? |
|
|
"Mirek Fidler" <cxl (AT) volny (DOT) cz> wrote
| Quote: | very significant milestone towards standardization. I am presently
cautiously optimistic that this functionality will make it into C++0X.
Can I honestly ask about the composition issue?
struct C {
Foo a; // has standard Foo(const Foo&) constructor
Bar a; // has both standard and move constructor
};
What kinds of constructor will C have?
|
As far as I know, even if both Foo and Bar have move constructors, the
automatically generated copy contructor for C will use Foo and Bar's copy
constructors. You can, of course define your own move constructor
struct C {
Foo a; // has standard Foo(const Foo&) constructor
Bar b; // has both standard and move constructor
Foo (const Foo &source) : a(source.a), b(source.b) {}
Foo (Foo &&source) : a(source.a), b(std::move(source.b)) {}
};
Note that this is exception safe, assuming that Bar's move constructor
cannot throw (the literature I've read on move constructors indicates that,
like destructors and specialized swap() functions, they should not throw).
If Foo's copy constructor throws then Bar's move constructor won't have been
called so source will remain unchanged. On the other hand, if we were to
change the structure so that b were defined before a, then this move
constructor would not be exception safe; if Foo's copy constructor threw an
exception after Bar's move constructor changed source, then source would
remain in an altered state.
I think we need two new additions to tr1::type_traits: has_nothrow_move and
has_nothrow_move_assign. These would be of great help in templated code for
avoiding the above problem. For instance, we could give a tr1::tuple a move
constructor if and only if each of its components satisfied
has_nothrow_move.
Joe Gottman
Joe Gottman
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Wed Aug 03, 2005 10:00 am Post subject: Re: Rvalue references -- a done deal? |
|
|
In article <3laanjF11b3j6U1 (AT) individual (DOT) net>,
Mirek Fidler <cxl (AT) volny (DOT) cz> wrote:
| Quote: | very significant milestone towards standardization. I am presently
cautiously optimistic that this functionality will make it into C++0X.
Can I honestly ask about the composition issue?
|
Of course.
| Quote: | struct C {
Foo a; // has standard Foo(const Foo&) constructor
Bar a; // has both standard and move constructor
};
What kinds of constructor will C have?
|
C will have only:
C(const C&);
There are currently no plans to implicitly generate move constructors or
move assignment operators. I consider this a feature, not a bug.
Implicit and automatic code generation when it can not be assured that
the automatically generated code is correct is a sure way to generate
run time errors. C++ had to make this compromise with copy constructors
and assignment operators for C compatibility. It need not make such a
compromise now.
That being said, there is interest on the committee in extending N1717
to allow the explicit request to automatically generate these members.
It might look something like:
struct C {
Foo a; // has standard Foo(const Foo&) constructor
Bar a; // has both standard and move constructor
C(C&&) {default}
C& operator=(C&&) {default}
};
In this scenario there is documented evidence that the programmer has
thought about these members, and made a decision to implement them.
This makes automatic code generation less error prone.
However I haven't seen such a proposal in writing yet, and I am not
actively working on one myself.
-Howard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Mirek Fidler Guest
|
Posted: Wed Aug 03, 2005 1:19 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
| Quote: | Of course.
struct C {
Foo a; // has standard Foo(const Foo&) constructor
Bar a; // has both standard and move constructor
};
What kinds of constructor will C have?
C will have only:
C(const C&);
There are currently no plans to implicitly generate move constructors or
move assignment operators.
|
Thank you. What a pitty :)
| Quote: | I consider this a feature, not a bug.
|
Sure.
| Quote: | Implicit and automatic code generation when it can not be assured that
the automatically generated code is correct is a sure way to generate
run time errors.
|
Well, I believe that rules are quite simple and obvious here, but I
understand that that at the moment you have better things to do than to
discuss it with me. And it is obviously too late now.
This makes me a little bit sad as this way r-value reference provides
just a bit of syntactic sugar over MOJO... (IMHO! And with all respect
to your work!).
Mirek
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Wed Aug 03, 2005 3:24 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
In article <zWTHe.83714$3j2.2896451 (AT) twister (DOT) southeast.rr.com>,
"Joe Gottman" <jgottman (AT) carolina (DOT) rr.com> wrote:
| Quote: | I think we need two new additions to tr1::type_traits: has_nothrow_move and
has_nothrow_move_assign. These would be of great help in templated code for
avoiding the above problem. For instance, we could give a tr1::tuple a move
constructor if and only if each of its components satisfied
has_nothrow_move.
|
I would not object to these additions. They would nicely complement the
existing has_trivial_copy and has_trivial_assign.
That being said, I would have misgivings about restricting the tuple
move constructor as you suggest. I think it would be good to have such
a restriction, I just don't think it is practical with our current run
time throw specs.
That is, in order for has_nothrow_move to be reliably set correctly, one
needs to decorate the move constructor with throw(). But coders are
understandably very hesitant to decorate their no-throw functions in
this way because of the fear of generating needless calls to
unexpected().
The other alternative is to specialize has_nothrow_move for each of your
classes where this applies. But this also seems tedious and error prone.
We have existing experience (believe it or not) to draw on here:
destructors.
At one time I toyed with the idea of decorating the container
destructors with throw(). After all, they better not. But as soon as I
did I noticed a significant increase in code size, at least for those
instantiations involving user-defined types. I could've asked my
customers to start decorating their destructors with throw(), and thus
the compiler could optimize out the unexpected() calls. But this simply
shifts the problem from ~container() to ~A(). I didn't feel I could
pass this problem on to my customers like this.
Deciding that no destructors can throw, and thus should be marked with
throw(), is a lot like const. You either use it correctly 100%, or you
don't use it all. Unlike the const case, using throw() less than 100%
of the time leads to compiling and correct, but unoptimized code (i.e.
when you make a mistake, the effects are subtle).
I would love to find a good solution to this problem (for destructors,
for move, for swap, etc.) - like maybe:
void foo() static throw();
But right now the best solution I know of is to just say "don't do
that", which is how we currently handle exceptions and destructors
(17.4.3.6p2). <sigh>
-Howard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Fuz Guest
|
Posted: Wed Aug 03, 2005 6:45 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
I believe there is an advantage in having the automatic generation of
move constructors. Take the following example:
template <typename T>
struct wrapper
{
T t;
};
wrapper<MovableType> will not have move semantics by default, as per
the proposal. This prevents certain optimisation opportunities, so the
author of wrapper<T> might decide to add an explicit move constructor:
template <typename T>
struct wrapper
{
T t;
wrapper(wrapper&& r) : t(r) {}
};
However, the introduction of the constructor prevents wrapper<PODType>
from ever being POD, which prevents (in the eyes of the Standard)
certain other optimisation opportunities, most notably: memcpy-ability
of an array of wrapper<T>.
Unless the explicit default-generation functions go ahead, and their
presence do not affect the PODness of a type, it seems to me that there
is no way of writing wrapper<T> so that it has the same traits as plain
T.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Wed Aug 03, 2005 10:35 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
In article <1123091595.975587.47190 (AT) g43g2000cwa (DOT) googlegroups.com>,
"Fuz" <srobb (AT) reflectionsinteractive (DOT) com> wrote:
| Quote: | I believe there is an advantage in having the automatic generation of
move constructors. Take the following example:
template <typename T
struct wrapper
{
T t;
};
wrapper
the proposal. This prevents certain optimisation opportunities, so the
author of wrapper<T> might decide to add an explicit move constructor:
template <typename T
struct wrapper
{
T t;
wrapper(wrapper&& r) : t(r) {}
wrapper(wrapper&& r) : t(std::move(r.t)) {}
};
However, the introduction of the constructor prevents wrapper
from ever being POD, which prevents (in the eyes of the Standard)
certain other optimisation opportunities, most notably: memcpy-ability
of an array of wrapper
Unless the explicit default-generation functions go ahead, and their
presence do not affect the PODness of a type, it seems to me that there
is no way of writing wrapper<T> so that it has the same traits as plain
T.
|
It is true that under current rules, wrapper<T> can no longer be a POD.
There has been a separate proposal for that issue (which isn't unique to
move semantics): N1356.
That being said, the explicit move constructor will not effect the
trivialness of wrapper's copy constructor, nor the result of
has_trivial_copy<wrapper::value (given compiler support). In
practice, I've found has_trivial_copy far more useful than is_pod.
For example, vector::insert can be highly optimized in this regard if
has_trivial_copy, has_trivial_assign and has_trivial_destructor all
answer true. This is far less constrained than the current POD
definition which additionally requires:
* no protected or private data members.
* no base classes.
So imho, retaining POD status is of limited value. I don't usually care
about the existence of base classes or private members. I usually care
about the trivialness of special members.
On the other side of this issue, the danger of automatically and
implicitly generating incorrect code is quite significant. Self
referencing classes just are not that rare.
Consider someone who has an existing class A, and doesn't really care
about move semantics, but starts using A with a new
rvalue-reference-aware compiler/std::lib. If A self-references, their
std::vector<A> could break (at run time - memory corruption likely) just
with a simple recompile. Such gross backwards incompatibilities with
C++03 are a show-stopper.
-Howard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Mirek Fidler Guest
|
Posted: Thu Aug 04, 2005 9:28 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
| Quote: | Consider someone who has an existing class A, and doesn't really care
about move semantics, but starts using A with a new
rvalue-reference-aware compiler/std::lib. If A self-references, their
std::vector<A> could break (at run time - memory corruption likely) just
with a simple recompile. Such gross backwards incompatibilities with
C++03 are a show-stopper.
|
Thank you for explanation. This is something I have never considered (I
am way to deep in moving bussines to create self-referencing classes :)
Then again, if this is the deal, perhaps you could avoid generating
move-constructor as soon as class has any other copy constructor defined
(I mean, by programmer, not default).
I think that if there is standard default constructor generated for
self-referencing class, code is as broken now as it would be with
default move constructor...
Mirek
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Fuz Guest
|
Posted: Thu Aug 04, 2005 9:30 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
Is it true that types with trivial copy constructors (but otherwise
non-POD) can be memcpy'd? I was always under the impression that only
PODs could be treated as a 'bag of bits' (certainly, that's the message
I've seen given by many experts on this subject). Personally, I think
that 'trivial copy' and 'trivial assign' suggests that's exactly what
can be done... it does exactly what it says on the tin. I can't
remember seeing that specified in the Standard, however.
Also, the addition of a constructor would also require the default
constructor of wrapper<T> to be defined in order to make it
default-constructable. This would prevent any
has_trivial_constructor<T> optimisations. Unless... is an
implementation allowed to 'see through' the definitions of the various
special member functions and give accurate trait information? e.g.:
template <typename T>
struct wrapper
{
test() {}
test(const test& r) : t(r.t) {}
test(test&& r) : t(std::move(r.t)) {}
test& operator=(const test& r) { x = r.t; return *this; }
test& operator=(test&& t) { t = std::move(r.x); return *this; }
~test() {}
T t;
};
// Do these fire?
static_assert(std::has_trivial_constructor<T>::value);
static_assert(std::has_trivial_copy<T>::value);
static_assert(std::has_trivial_move<T>::value);
static_assert(std::has_trivial_assign<T>::value);
static_assert(std::has_trivial_move_assign<T>::value);
static_assert(std::has_trivial_destructor<T>::value);
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Fri Aug 05, 2005 7:57 am Post subject: Re: Rvalue references -- a done deal? |
|
|
In article <1123178080.023202.320930 (AT) f14g2000cwb (DOT) googlegroups.com>,
"Fuz" <srobb (AT) reflectionsinteractive (DOT) com> wrote:
| Quote: | is an
implementation allowed to 'see through' the definitions of the various
special member functions and give accurate trait information? e.g.:
template <typename T
struct wrapper
{
test() {}
test(const test& r) : t(r.t) {}
test(test&& r) : t(std::move(r.t)) {}
test& operator=(const test& r) { x = r.t; return *this; }
test& operator=(test&& t) { t = std::move(r.x); return *this; }
~test() {}
T t;
};
// Do these fire?
static_assert(std::has_trivial_constructor
static_assert(std::has_trivial_copy<T>::value);
static_assert(std::has_trivial_move<T>::value);
static_assert(std::has_trivial_assign<T>::value);
static_assert(std::has_trivial_move_assign<T>::value);
static_assert(std::has_trivial_destructor<T>::value);
|
By current definitions, they fire. There is a very specific definition
of "trivial" in chapter 12, and user defined special members are never
trivial, no matter how trivial they are. ;-)
-Howard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Fuz Guest
|
Posted: Fri Aug 05, 2005 3:14 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
Thanks, I suspected that was the case. Would the proposed
extensions to N1717 allow the correct traits to be generated? I would
hope that wrapper<T> could be written as:
template <typename T>
struct wrapper
{
test() { default }
test(const test&) { default }
test(test&&) { default }
test& operator=(const test&) { default }
test& operator=(test&&) { default }
~test() { default }
T t;
};
This would allow T's traits to drop through to wrapper<T> and pass all
the static_asserts mentioned previously.
And what about the memcpy-ing issue? Is has_trivial_copy enough to
ensure that you can create a whole load of new objects using memcpy?
Item 96 of C++ Coding Standards suggests that you need PODness, but you
(and Boost: http://www.boost.org/libs/type_traits#example ) suggest
that only a trivial copy is required, regardless of trivialness of the
other constructors and destructor. And I can't find anything in the
standard which specifies it one way or the other.
I still think this is on-topic, by the way; I don't want the explicit
generation of move constructors to break whether I can memcpy an object
or not. I think Mirek Fidler's suggestion of preventing the automatic
generation of a move constructor if other user-defined constructors
exist is a good idea, and mirrors the behaviour of the automatic
generation of a default constructor. Though (again) the extension of
N1717 to allow an explicit automatically-generated default constructor
which gives an accurate has_trivial_constructor<wrapper result is
still an attractive prospect.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Fri Aug 05, 2005 5:49 pm Post subject: Re: Rvalue references -- a done deal? |
|
|
In article <1123245007.989224.311910 (AT) g43g2000cwa (DOT) googlegroups.com>,
"Fuz" <srobb (AT) reflectionsinteractive (DOT) com> wrote:
| Quote: | Thanks, I suspected that was the case. Would the proposed
extensions to N1717 allow the correct traits to be generated?
|
I hope so.
| Quote: | And what about the memcpy-ing issue? Is has_trivial_copy enough to
ensure that you can create a whole load of new objects using memcpy?
Item 96 of C++ Coding Standards suggests that you need PODness, but you
(and Boost: http://www.boost.org/libs/type_traits#example ) suggest
that only a trivial copy is required, regardless of trivialness of the
other constructors and destructor. And I can't find anything in the
standard which specifies it one way or the other.
|
Now that you mention it, I can't find it either. Otoh, the compiler has
to implement trivial copy constructors somehow and simply copying all
the bytes (whether or not using memcpy or just load/stores) seems like
the only reasonable thing to do.
| Quote: | I still think this is on-topic, by the way; I don't want the explicit
generation of move constructors to break whether I can memcpy an object
or not. I think Mirek Fidler's suggestion of preventing the automatic
generation of a move constructor if other user-defined constructors
exist is a good idea, and mirrors the behaviour of the automatic
generation of a default constructor. Though (again) the extension of
N1717 to allow an explicit automatically-generated default constructor
which gives an accurate has_trivial_constructor<wrapper result is
still an attractive prospect.
|
I really like N1717 and hope it (or equivalent functionality) gets
accepted. This combined with no implicit generation of move members
results in a very simple rule:
If you want it, you have to ask for it. If you want help implementing
it, use "default" (or whatever).
As opposed to: Sometimes this special member is generated for you, and
sometimes it isn't.
-Howard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|