std::unique_ptr<const Foo> result(new Foo);// ...return result;}
If you really need to convert, I suggest make it explicit:std::unique_ptr<const Foo> FooFactory() {std::unique_ptr<Foo> result(new Foo);
// ...return std::unique_ptr<const Foo>(std::move(result));}It would be clear what you are doing.
By the way, where I work we always write explicit casts.
> Coming back to the original topic, are you really suggesting the code above is the ideal form for teaching when to use std::move and when > not to? I think "return result;" is much simpler.
If you have to convert from std::unique_ptr<Foo> to std::unique_ptr<const Foo>the following code WON'T COMPILE;return result;Try it in your compiler!
On Mon, Jun 24, 2013 at 1:08 PM, Xeo <hivem...@hotmail.de> wrote:
> I remember sending you and Mike a reminder about that some months ago, and
> was wondering, did you actually talk about this at the Bristol meeting?
No. For CWG, the Bristol meeting was almost entirely occupied by
reviewing C++14 feature wording. I don't recall seeing this on the
issues list, either, but perhaps I just missed it.
It's surprisingly hard to come up with a good, teachable set of rules for when to use std::move. For example, it would be nice to be able to say "you can leave out std::move when returning a named local variable", but this is not always the case.
Conversely, it would be nice to be able to say "When in doubt, just use std::move if you want move semantics, because it never hurts", but std::move can in fact be a pessimization:std::array<Foo, 10000> MakeHugeArray() {std::array<Foo, 10000> result;// ...return std::move(result);}As written, the return statement incurs 10,000 invocations of Foo's move constructor (or, worse, its copy constructor), but if std::move is eliminated, the return statement becomes effectively free, because it's an elidable copy/move.
In this case it's not at all clear to me how to fix the problem; it seems like a fix would either require special-casing std::move (which seems like a hack, and breaks the convention that the core-language standard tries not to refer to the library standard), or require the implementation to 'see into' the implementation of a function called in a return statement (which seems impractical).
I think it's worth trying to fix these issues, despite the difficulties, because being able to provide reliable "rules of thumb" would substantially improve the learning curve for std::move. Can anyone suggest how these issues could be fixed?
template<class T, size_t n>
array { T storage[n]; /* some non-virual member function here... */ }
On 2013–06–25, at 2:42 AM, Geoffrey Romer <gro...@google.com> wrote:It's surprisingly hard to come up with a good, teachable set of rules for when to use std::move. For example, it would be nice to be able to say "you can leave out std::move when returning a named local variable", but this is not always the case.That doesn’t sound like something that should be taught. Students shouldn’t have the impression that they should avoid move, or omit it just because they can.
Conversely, it would be nice to be able to say "When in doubt, just use std::move if you want move semantics, because it never hurts", but std::move can in fact be a pessimization:std::array<Foo, 10000> MakeHugeArray() {std::array<Foo, 10000> result;// ...return std::move(result);}As written, the return statement incurs 10,000 invocations of Foo's move constructor (or, worse, its copy constructor), but if std::move is eliminated, the return statement becomes effectively free, because it's an elidable copy/move.I'm pretty sure there’s a DR for this. First-draft code doesn’t need to run full speed anyway. Students should learn general techniques for finding bottlenecks, not every performance quirk and pitfall.
When fixing this code, it would be a good idea to add a comment that the result is expected to be constructed in-place, hence neither moved nor copied.By the way, this code is still giving you exactly what you asked for. Asking for a move when you actually want copy elision is, though reasonable, a confusion of two completely different things.
In this case it's not at all clear to me how to fix the problem; it seems like a fix would either require special-casing std::move (which seems like a hack, and breaks the convention that the core-language standard tries not to refer to the library standard), or require the implementation to 'see into' the implementation of a function called in a return statement (which seems impractical).It may be doable for inline functions. Perhaps some future language iteration will see through the thicket.I think it's worth trying to fix these issues, despite the difficulties, because being able to provide reliable "rules of thumb" would substantially improve the learning curve for std::move. Can anyone suggest how these issues could be fixed?Say move() when you want a move.
Debug the rest, and be aware that moves still carry a cost which may be as much as a copy.
On Thu, Jun 26, 2014 at 6:17 PM, David Krauss <pot...@gmail.com> wrote:That doesn’t sound like something that should be taught. Students shouldn’t have the impression that they should avoid move, or omit it just because they can.Really? You wouldn't even teach students to omit move in an expression like this?Sink(std::move(Source()));
When fixing this code, it would be a good idea to add a comment that the result is expected to be constructed in-place, hence neither moved nor copied.By the way, this code is still giving you exactly what you asked for. Asking for a move when you actually want copy elision is, though reasonable, a confusion of two completely different things.Can you give an example of when a programmer would not want a copy elision?
Say move() when you want a move.That's just begging the question; I'm trying to teach people how to know when they should want a move
Debug the rest, and be aware that moves still carry a cost which may be as much as a copy.Would you say, then, that one should never apply std::move to a copyable type?
On 2014–06–28, at 3:43 AM, 'Geoffrey Romer' via ISO C++ Standard - Future Proposals <std-pr...@isocpp.org> wrote:That doesn’t sound like something that should be taught. Students shouldn’t have the impression that they should avoid move, or omit it just because they can.Really? You wouldn't even teach students to omit move in an expression like this?Sink(std::move(Source()));That’s going a bit far. Students should know that move casts an object-semantic lvalue into a value-semantic rvalue, and application to an rvalue is always redundant. But that’s not avoiding it, or opportunistic omission, it follows from the underlying theory.
When fixing this code, it would be a good idea to add a comment that the result is expected to be constructed in-place, hence neither moved nor copied.By the way, this code is still giving you exactly what you asked for. Asking for a move when you actually want copy elision is, though reasonable, a confusion of two completely different things.Can you give an example of when a programmer would not want a copy elision?It’s an optimization, not a choice. Teaching its interaction with moving is asks the student to think about two theories at once, which almost by definition relegates it to a more advanced course.
Say move() when you want a move.That's just begging the question; I'm trying to teach people how to know when they should want a moveI mean, say move() when you want an ownership transfer.
Debug the rest, and be aware that moves still carry a cost which may be as much as a copy.Would you say, then, that one should never apply std::move to a copyable type?Absolutely not. For one thing, that often happens in generic programming. I simply mean that while chasing performance bugs, after the fact of writing a first draft, code with move semantics should not be dismissed out of hand as “already fast.”
On Fri, Jun 27, 2014 at 3:30 PM, David Krauss <pot...@gmail.com> wrote:
That’s going a bit far. Students should know that move casts an object-semantic lvalue into a value-semantic rvalue, and application to an rvalue is always redundant. But that’s not avoiding it, or opportunistic omission, it follows from the underlying theory.I'm curious; if you don't think students should be taught about this option, do you think it was a mistake for the language to go so far out of its way (q.v. [class.copy]/p32) to enable it?
In any event, this is a moot point. C++14 resolves the defect I was referring to here, so we _can_ now teach that you can always omit std::move when returning a variable that's local to the scope you're returning from.
It’s an optimization, not a choice. Teaching its interaction with moving is asks the student to think about two theories at once, which almost by definition relegates it to a more advanced course.Yes, which is exactly I don't want it to have _any_ interaction with moving, so that I don't have to teach about that interaction.
"Ownership" normally refers to the responsibility to explicitly invoke a cleanup operation (cf. [unique.ptr]/p1), and so doesn't apply to many situations where move() is appropriate, or even necessary. It's possible to generalize the notion of ownership so that it applies to those situations too, but at that point "ownership transfer" becomes basically synonymous with move, and your advice again becomes circular.
Oh, I certainly agree with that; my goal is to reduce the number of performance bugs that people write (or fear they will write) in the first place.