5

implicitly deleted move constructor (C's move) looks like non-declared move and compiler try to use the copy constructor (C's copy).

Why there is the difference between the implicitly deleted move (C's move) and explicitly deleted move (B's move)?

There are some explanations, are there any more details?

Why is the move constructor neither declared nor deleted with clang?

@dyp comment:

Because an implicitly deleted move constructor is not declared

and link to DR1402:

http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1402

A defaulted move constructor that is defined as deleted is ignored by overload resolution (13.3 [over.match]). [Note: A deleted move constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead. —end note]

http://en.cppreference.com/w/cpp/language/move_constructor

(since C++14)The deleted implicitly-declared move constructor is ignored by overload resolution (otherwise it would prevent copy-initialization from rvalue)

sample code:

#include <utility>

class A {
public:
    A() = default;
    A(const A&) = delete;
    A(A&&) = delete;
};

class B : public A {
public:
    B() = default;
    B(const B&) = delete;
    B(B&&) = delete; // explicitly deleted move
};

class C: public A {
public:
    C() = default;
    C(const C&) = default; // implicitly deleted copy because A's copy is deleted
    C(C&&) = default; // implicitly deleted move because A's move is deleted
};

int main() {
    A a1;
    A a2(std::move(a1)); // error, A's move is explicitly deleted

    B b1;
    B b2(std::move(b1)); // error, B's move is explicitly deleted

    C c1;
    C c2(std::move(c1)); // error, C's **copy** is implicitly deleted

    return 0;
}

compiler message:

Apple LLVM version 7.0.0 (clang-700.1.76)
clang++ -std=c++11 3.cpp

3.cpp:26:7: error: call to deleted constructor of 'A'
    A a2(std::move(a1)); // error, A's move is explicited deleted
      ^  ~~~~~~~~~~~~~
3.cpp:7:5: note: 'A' has been explicitly marked deleted here
    A(A&&) = delete;
    ^
3.cpp:29:7: error: call to deleted constructor of 'B'
    B b2(std::move(b1)); // error, B's move is explicited deleted
      ^  ~~~~~~~~~~~~~
3.cpp:14:5: note: 'B' has been explicitly marked deleted here
    B(B&&) = delete; // explicitly deleted move
    ^
3.cpp:32:7: error: call to implicitly-deleted copy constructor of 'C'
    C c2(std::move(c1)); // error, C's **copy** is implicited deleted
      ^  ~~~~~~~~~~~~~
3.cpp:20:5: note: explicitly defaulted function was implicitly deleted here
    C(const C&) = default; // implicitly deleted copy
    ^
3.cpp:17:10: note: copy constructor of 'C' is implicitly deleted because base class 'A' has a deleted copy constructor
class C: public A {
         ^
3.cpp:6:5: note: 'A' has been explicitly marked deleted here
    A(const A&) = delete;
    ^
3 errors generated.
Community
  • 1
  • 1
chyojn
  • 161
  • 1
  • 5

1 Answers1

1

std::move does not necessarily force moving, it just casts the argument as an xvalue so that it may be moved, if possible. It can be ignored, and is most times unnecessary to call std::move to make the compiler move, or even better optimize copies away completely.

http://en.cppreference.com/w/cpp/utility/move

It is exactly equivalent to a static_cast to an rvalue reference type.

static_cast<typename std::remove_reference<T>::type&&>(t)
J.P.
  • 350
  • 2
  • 11
  • Sorry you're right. I think n.m is mostly right, what the compiler does to generate or fail to generate the binary code is not always set by the standard. In this case it falls through different paths before finding the error, and that may be OK or out of scope of the standard. – J.P. Nov 05 '15 at 10:47
  • For info Visual Studio 2013 gives a different error: [C2610](https://msdn.microsoft.com/en-us/library/aa748670.aspx): 'C::C(C &&)' : is not a special member function which can be defaulted. Looks a bit clearer than LLVM as caused by the fact that you can't default a move constructor of a class derived from one which has none, but still doesn't explain you this. PS sorry I can't comment in the original post due to low rep – J.P. Nov 05 '15 at 10:57
  • @J.P. VS2013's message doesn't shed any light on the problem, because VS2013 simply doesn't support defaulted move functions. – Sebastian Redl Nov 05 '15 at 11:35