Boost logo

Boost :

Subject: Re: [boost] [move] interest: the pass-by-value and swap idiom, and explicit copy constructors
From: Krzysztof Czainski (1czajnik_at_[hidden])
Date: 2014-02-15 04:54:08


2014-02-15 1:13 GMT+01:00 Adam Wulkiewicz <adam.wulkiewicz_at_[hidden]>:

> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk