From: Howard Hinnant (hinnant_at_[hidden])
Date: 2002-02-04 19:40:24
On Monday, February 4, 2002, at 06:27 PM, Jeremy Siek wrote:
> Nice description and motivation for move semantics.
> On Mon, 4 Feb 2002, Howard Hinnant wrote:
> hinnan> What remains to be done is to settle on a uniform syntax for
> hinnan> semantics. John Maddock has suggested:
> hinnan> T b = std::move(a);
> Would this mean we'd also have to rely on cooperation from operator=?
John Maddock has suggested that std::move return the struct
std::move_t<T>. Then the class T could create a constructor and
assignment operator that accepted a std::move_t<T>. This has a nice
parallel with the current requirements of implementing copy semantics.
> Wouldn't it be better to keep things simple with something like this
> std::move(a, b); // a -> b
I'm open to just about anything!
> hinnan> Perhaps boost::auto_vector could experiment with this. The big
> hinnan> stumbling block I've had to date is allowing move from a
> temporary T,
> hinnan> but disallowing move from a const T, and packaging this up in a
> hinnan> relatively reusable package so that giving your class move
> semantics is
> hinnan> no harder than giving it copy semantics.
> Well, non-const member functions have the property that you can call
> on temporaries but not on const objects. So you could do this:
> Of course, this would require invasive changes to current classes, and
> couldn't have the same syntax for builtins.
I think invasive changes to current classes is unavoidable. Only vector
knows how to move itself. About the only (std) classes (with
non-trivial move) that everyone already knows how to move is list
(splice) and auto_ptr (copy).
And your point about builtins (scalars) is right on the mark. We *must*
have the same move syntax for scalars, and that can be implemented as a
copy. Without the same syntax for scalars, templated code wanting to
move goes out the window.
And on the subject of templated code using move: The code must be able
to determine if the template type supports move semantics. John Maddock
to the rescue again, (with significant help from Andrei Alexandrescu)
has suggested: Use is_convertible to discover if a std::move_t<T> will
convert to T (via T's converting constructor taking a std::move_t<T>).
And a rule that says if you support move construction, you must also
support move assignment.
On the other hand, if we can detect the presence of move semantics, then
scalars could be defined to not support move, and thus move syntax need
not accommodate scalars. A design worth exploring...
> Or perhaps we just need to file a DR to once again allow temporaries to
> bound to non-const references. On the surface that restriction made a
> of sense, but deep down it was wrong.
I would be against such a DR. But I would be violently in favor of a
language change that allowed a method to detect the difference between a
temporary parameter and a const parameter.
tantalizingly close in sub-issue 2:
template<class T> void g(T); // #1
template<class T> void g(T&); // #2
If this were allowed, temporaries would bind to g(T), non-const lvalues
would bind to g(T&) and const lvalues would bind to g(T&) with T ==
const T. And then g(T&) could easily distinguish between T and const T
with is_const<T> (Metrowerks actually works this way, by accident, not
by design). However, the word on the street is that this sub-issue will
be declared ambiguous.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk