why move-only object can not add explicit keyword?

Viewed 117

test.cpp:

#include <iostream>

class MacroObject {
public :
    MacroObject() = default;

    MacroObject(const MacroObject&) = delete ;
    MacroObject& operator=(const MacroObject&) = delete;

    explicit MacroObject(MacroObject&&) = default;
    MacroObject& operator=(MacroObject&&) = default;

    int init(){return 0;}
    int get(){return 0;}
};

MacroObject getObj(){
    MacroObject obj;
    obj.init();
    return obj;
}

int main(){
    MacroObject obj{getObj()};
    std::cout << obj.get() << std::endl;
    return 0;
}

I use this command with g++ 4.8.5:

g++ -std=c++11 test.cpp

I get this error message:

test.cpp: In function 'MacroObject getObj()':
test.cpp:19:8: error: use of deleted function 'MacroObject::MacroObject(const MacroObject&)'
 return obj;
        ^
test.cpp:6:1: error: declared here
 MacroObject(const MacroObject&) = delete ;
 ^

When I remove explicit, it is ok.

Why g++ uses the deleted copy-constructor and not the move-constructor?

1 Answers

By making the move constructor explicit you can't do

MacroObject x;
MacroObject y = std::move(x);

but can do

MacroObject y(std::move(x));

The return from the function, even in newer C++ versions where mandatory copy/move elision (NRVO) is in effect, tries to match the top version. Since that isn't a match, it checks the copy constructor. Since that is deleted, it stops with a failure.

It does not go on to try explicit versions. They are not candidates.

Making the copy and move constructors explicit makes the class useless with many standard library classes / functions so I recommend not making them explicit.

Related