0
votes

I have some ambiguities about "move" semantics: What I've read is that a move constructor or assignment is defined implicitly as a deleted function if the class has defined one of its own copy-control members. But I have this code:

int main()
{
    struct A {
        A() = default;
        A(const A&) { cout << "A's cpy-ctor\n"; } // this forces move ctor to be defined as a deleted function
        //A(A&&) = default;
        //A(A&&) = delete; // if uncomment this line then the line below calling std::move will cause an error(referencing a deleted function).
    };

    A a = std::move(A{}); // move not available then use copy-ctor instead


    std::cout << "\ndone\n";
}
  • If I uncomment the first commented line then it is OK as I've guessed: the copy-constructor is used instead of the move-ctor as the fact it is not explicitly defined.

    • But if I uncomment the second commented line I'll get compile-time error on calling std::move complaining about a deleted function. But why the compiler doesn't use copy-ctor instead directly?

    • What does mean defulting this move-ctor and how does that affect function-matching?

Thank you so much!

1
the copy-constructor is used instead of the move-ctor - are you sure about that? - NutCracker
@NutCracker: Do you say no? if so please explain. - Maestro
Take a look here and tell me what you see - NutCracker

1 Answers

1
votes

When you have a user declared copy constructor, then the move constructor and move assignment are not declared which is not the same as deleted.

This means that the only valid signature is A(A const &) - the copy constructor.

So, when you call the constructor with an rvalue reference (what std::move explicitly provides), the copy constructor whose signature is a lvalue reference to const will be the best match.

However, if you define the move constructor as deleted, then that signature is found, and since it is the best match the compiler does not even try to match with the copy constructor. However, since the move constructor is deleted, the compiler says "hey I found the best match, which is the move constructor, so I'll use that one, but it is defined as deleted, so you are not allowed to call it."