Re: Implicit move constructor rules in c++0x still badly broken?
On 22 Feb., 20:43, Howard Hinnant wrote:
Here's Dave's code, completed and instrumented:
#include <iostream>
class Y
{
int state_;
public:
enum {destructed = -2, moved_from, default_constructed};
Y() : state_(default_constructed) {}
Y(const Y& a) : state_(a.state_) {}
Y& operator=(const Y& a) {state_ = a.state_; return *this;}
Y(Y&& a) : state_(a.state_)
{
a.state_ = moved_from;
}
Y& operator=(Y&& a)
{
state_ = a.state_;
a.state_ = moved_from;
return *this;
}
~Y()
{
state_ = destructed;
}
explicit Y(int s) : state_(s) {}
friend
std::ostream&
operator<<(std::ostream& os, const Y& a)
{
switch (a.state_)
{
case Y::destructed:
os << "Y is destructed\n";
break;
case Y::moved_from:
os << "Y is moved from\n";
break;
case Y::default_constructed:
os << "Y is default constructed\n";
break;
default:
os << "Y = " << a.state_ << '\n';
break;
}
return os;
}
friend bool operator==(const Y& x, const Y& y)
{return x.state_ == y.state_;}
friend bool operator<(const Y& x, const Y& y)
{return x.state_ < y.state_;}
};
class InvariantChecker
{
Y* v_;
InvariantChecker(const InvariantChecker&);
InvariantChecker& operator=(const InvariantChecker&);
public:
explicit InvariantChecker() : v_(0) {}
explicit InvariantChecker(Y& v) : v_(&v) {}
~InvariantChecker()
{
if (v_)
std::cout << *v_ << '\n';
}
};
Y
f(bool choose)
{
Y a(1), b(2);
InvariantChecker xa(a), xb(b);
// Incorrect comment follows:
// The use of ?: guarantees that there will be no copy elision.
// Instead, either a or b will be *moved* into the return value.
return choose ? a : b;
Apparently, GCC won't move from a or b if you use this kind of return
expression. I'm not sure about what the standard draft says about this
case. But if you replace this line with
if (choose) return a; else return b;
you will see the following output
Y = 2
Y is moved from
(tested using GCC 4.5.1)
// xb and xa get destroyed here
// b and a get destroyed thereafter
}
int main()
{
Y y = f(true);
}
Using g++-4.4 with libc++ I get the identical output. To demonstrate
Dave's point I expect to see:
Y is moved from
Right. Change the above line and you will see this output.
On 23 Feb., 12:09, Dragan Milenkovic wrote:
BTW, I still have issues with "implicit move return". :-(
What is your solution? :-)
Let me stress again that I don't think forcing users to write
return std::move(some_function_local_object);
instead of
return some_function_local_object;
is a good idea. Here's why:
- The use of std::move() DISABLES any kind of RVO but RVO would be
even better than a move construction of the return value.
- If RVO cannot be applied, a move construction is almost always
the right thing to do (except in corner cases like the above one).
I wouldn't want to be forced to write std::move all the time.
Cheers!
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]