[cfe-dev] Move constructor forces copy assignment to be implicitly defaulted?
Steve Ramsey
clang at lucena.com
Tue May 29 10:45:24 PDT 2012
On May 28, 2012, at 6:21 PM, Howard Hinnant wrote:
> #include <type_traits>
> #include <string>
>
> struct A
> {
> std::string s;
> };
>
> static_assert(std::is_nothrow_move_constructible<A>::value,
> "A should be nothorw move constructible");
>
> struct B
> : public A
> {
> ~B();
> };
>
> static_assert(std::is_nothrow_move_constructible<B>::value,
> "B should be nothorw move constructible");
>
> A makeA() {
> A a;
> return a;
> }
>
> B makeB() {
> B b;
> return b;
> }
>
> int main() {
> A a = makeA();
> B b = makeB();
> }
>
> test.cpp:18:1: error: static_assert failed "B should be nothorw move constructible"
> static_assert(std::is_nothrow_move_constructible<B>::value,
> ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 1 error generated.
>
> Since the move constructor in B has been suppressed, it is no longer nothrow to move B. Now if you add:
>
> B() = default;
> B(B&&) = default;
>
>
> then everything will compile.
This is an interesting example, but it muddies things a bit. The std::string member in A is not nothrow-copy-constructible, which is why B is initially not nothrow-move-constructible (though it is still move-constructible, as std::string is copy-constructible); this all follows from the Note in 12.8 p9. Once that is clear, the point of the example comes through; namely, that the move constructor that had been undeclared as per 12.8 p9 can be explicitly declared and defined as defaulted, and the default definition will be nothrow-move-constructible all the way down.
Steve
More information about the cfe-dev
mailing list