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 08:58:36


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

> Hi,
>
> Krzysztof Czainski wrote:
>
>> 2014-02-15 1:13 GMT+01:00 Adam Wulkiewicz <adam.wulkiewicz_at_[hidden]>:
>>
>> 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.
>>
>
> Yes, in GCC4.7, Clang3.2, MinGW 4.7, VS2010, VS2013.
>
> However VS isn't good for testing the standard. For instance it doesn't
> implicitly delete the copy ctor if move ctor is defined and therefore
> permits copying.
>
>
>
>> Assuming that my understanding is correct, with copy and swap the move
>>> assignment operator can't be implicitly declared.
>>>
>> Why?
>>
>
> I'll leave the interpretation of the standard to smarter than me but
> according to this: http://en.cppreference.com/w/cpp/language/move_operator
>
> <cite>
> The implicitly-declared or defaulted move assignment operator for class
> |T| is defined as /deleted/ in any of the following is true:
> ...
> |- T| has a non-static data member or a direct or virtual base without a
> move assignment operator that is not trivially copyable.
> </cite>
>
> Our member isn't trivially copyable and hasn't declared move assignment,
> because our assignment takes parameter by value not by && so it's not move
> assignment. Well, not the explicitly defined one, according to the same
> page:
>
> <cite>
> A move assignment operator of class |T| is a non-template non-static
> member function with the name operator= that takes exactly one parameter of
> type T&&, const T&&, volatile T&&, or const volatile T&&.
> </cite>
>
> Btw, according to page: http://en.cppreference.com/w/
> cpp/language/as_operator
>
> <cite>
> A copy assignment operator of class |T| is a non-template non-static
> member function with the name operator= that takes exactly one parameter of
> type T, T&, const T&, volatile T&, or const volatile T&
> </cite>
>
> so our assignment operator is copy assignment.
>

Hmm, it's a pity IMHO, but I agree. So if class X has a base or member Y
with an assignment operator taking Y by value, it implies X's
auto-generated move assignment is declared deleted. Can anyone please
confirm these requirements with the standard?

> So is there an implicitly declared move assignment in the member class?
> According to the first mentioned page:
>
> <cite>
> If no user-defined move assignment operators are provided for a class type
> (struct, class, or union), and all of the following is true:
>
> * there are no user-declared copy constructors
> * there are no user-declared move constructors
> * there are no user-declared copy assignment operators
> * there are no user-declared destructors
> * the implicitly-declared move assignment operator would not be
> defined as deleted
>
> </cite>
>
> AFAIU only the last point is true.
>
> So this is my reasoning. I'd say that there is a bug in GCC4.8, but maybe
> it's a feature ;)
>
> Btw, in the same time std::is_move_assignable<Matrix>::value == true
> (MinGW 4.7)

Interesting, thanks for your input, Adam.

Regards,
Kris


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