
2014-02-15 1:13 GMT+01:00 Adam Wulkiewicz
Hi,
Krzysztof Czainski wrote:
Hello,
I would like to ask about interest in an idea of mine. I described it in detail [1] and implemented it as part of my cz libraries [2].
In short, the idea presents: - an alternative to implicitly copyable and movable types: making them explicitly copyable; - a protocol for explicitly stating in code, where a copy is to be made (boost::copy()), which compliments the protocol for explicitly stating in code, where a move is allowed (std::move() or boost::move()); - a Boost.move extension for implementing movable types with use of the pass-by-value and swap idiom, backwards-compatible with C++98, which allows to choose copying policies (and eases changing between these policies during maintenance): - movable but not copyable, - movable and explicitly-copyable, - movable and copyable; - an example, showing how simply a CloneablePtr can thereby be implemented.
This extension to Boost.move is hosted and developed as part of my cz libraries [2], but it isn't tied to them at all. It only consists of two headers. I extracted the two headers together with samples and docs, and they are available as a zip archive [3].
I would be most excited if there was interest in adding this functionality to Boost.move, but in any case, all comments are much appreciated.
Regards, Kris
[1] http://kristoczaj.bitbucket.org/cz/copy_move_types.html [2] http://kristoczaj.bitbucket.org/cz/index.html [3] http://bitbucket.org/kristoczaj/cz/downloads/move-0.7.1.zip
Your proposal reminds me Scott Meyers' lecture (http://channel9.msdn.com/ Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler): "std::copy() doesn't copy and std::forward() doesn't forward"
I haven't seen this yet, thank you for this reference.
your boost::copy() is different because it indeed copies something ;).
I have a few questions.
1. I think that the results of the first example with Matrices (implicitly declared ctors and assignments) are wrong. What compiler do you use? I've tested it in GCC 4.7 and Clang 3.2 with -std=c++11.
I just tested it with MinGW-4.8, and I must say you are right, Adam -- thank you for pointing this out. I must have added the const in the first line of main(), and missed the fact, that output had changed - I apologize. The output I get with the const in there is: C++11 | C++98 -------------------- | -------------------- CopyMoveDemo() | CopyMoveDemo() CopyMoveDemo(const&) | CopyMoveDemo(const&) CopyMoveDemo(const&) | CopyMoveDemo(const&) ### | ### CopyMoveDemo(const&) | CopyMoveDemo(const&) swap CopyMoveDemo | swap CopyMoveDemo ~CopyMoveDemo() | ~CopyMoveDemo() CopyMoveDemo(&&) | CopyMoveDemo(__const&__) swap CopyMoveDemo | swap CopyMoveDemo ~CopyMoveDemo() | ~CopyMoveDemo() ### | ### ~CopyMoveDemo() | ~CopyMoveDemo() ~CopyMoveDemo() | ~CopyMoveDemo() ~CopyMoveDemo() | ~CopyMoveDemo() But without the const, i.e. Matrix a; in the first line of main(), the output is as presented in the paper. It makes sense, because a move() on a const object returns Matrix const&&, which simply chooses the copy constructor as the best overload in this case. a) can't move from a const object, this is a copy
Matrix const a; Matrix c = boost::move(a);
Right. So the correct example should be without the const - sorry. I've corrected this in the article. Should I maintain some change log? b) here I have a copy as well, probably because Matrix has a non-static
data member without a move assignment operator and that is is not trivially copyable c = boost::move(b); after declaring "proper" move assignment in the member class (instead of copy and swap) or using copy and swap + move ctor in Matrix everything works as expected.
Do you get a copy in C++11 here? I get a move() in C++11, and a copy in C++98. And that's what I expect, because C++11 auto-generates copy- and move-assignment operators, and both use the pass-by-value assignment of CopyMoveDemo correctly.
Assuming that my understanding is correct, with copy and swap the move assignment operator can't be implicitly declared.
Why?
So you'll be forced to declare it manually even in C++11.
I don't think so. I think, the auto-generated copy- and move-assignments work with it correctly. AFAIK the currently used move emulation doesn't have this limitation. Or am
I missing something?
In C++98 only a copy-assignment operator is auto-generated, so the class just isn't movable.
2. About the example with Matrices addition and moves, the one with e.g. this line:
Matrix e = boost::move(b) + c + d;
Is it just an example of using boost::move() needed by the next complimentary example of using boost::copy(), showing that you could do something like this?
Yes, this is just to show, that we can make this compile. It only makes sense if we no longer need `b` in this function, which may sometimes be the case.
Or do you think that this is the right way of implementing e.g. the addition to avoid temporary copies? I'm asking because it's a little too clever on my taste. IMHO the way with the 4 overloads is more intuitive.
I think, the 4 overload are kind of orthogonal to my explicit-copy proposal. I am proposing to make all copies explicit. And the purpose of the 4 overloads is so that more implicit copies can be avoided. One could combine both approaches. That would mean removing one of the 4 overloads, which makes an implicit copy, and taking advantage of the 3 remaining, while still requiring the copy to be explicit.
On some review it could certainly increase the value of WTF/minute ;) ( http://www.osnews.com/story/19266/WTFs_m).
I take your point. But still, sometimes I'd rather see pointed out in code, where copies are happening. Regards, Kris