Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why implicitly deleted move constructor call copy constructor?

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.
like image 985
chyojn Avatar asked Nov 10 '22 02:11

chyojn


1 Answers

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)
like image 164
J.P. Avatar answered Jan 04 '23 03:01

J.P.