Boost logo

Boost :

Subject: Re: [boost] [move] interest: the pass-by-value and swap idiom, and explicit copy constructors
From: Adam Wulkiewicz (adam.wulkiewicz_at_[hidden])
Date: 2014-02-15 08:11:32


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.

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)

Regards,
Adam


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