I've recently experienced some strange behaviour in my C++11 code.
I've got a class, which is only movable:
class only_move
{
public:
only_move() : value(0) {}
only_move(int value) : value(value) {}
only_move(const only_move&) = delete;
only_move& operator=(const only_move&) = delete;
only_move(only_move&&) = default;
only_move& operator=(only_move&&) = default;
int value;
};
And I've got another class, which contains an only_move
object:
class has_only_move_member
{
public:
has_only_move_member() = delete;
has_only_move_member(only_move&& value) : member(std::move(value)) {}
only_move member;
};
If I understood it correct, that means has_only_move_member
can't be copied, as the only_move
member can't be copied. This means has_only_move_member(const has_only_move_member&)
is deleted implicitly. Let's check that out:
has_only_move_member object(only_move(5));
has_only_move_member copy_of_object(object);
As expected, it prints out:
error: use of deleted function ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’
note: ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’ is implicitly deleted because the default definition would be ill-formed:
class has_only_move_member
Okay, so I moved on and put has_only_move_member
instances in a std::map
. As they don't have a copy constructor, I've moved them into it:
has_only_move_member object(only_move(5));
std::map<int, has_only_move_member> data;
data.emplace(5, std::move(object));
So far so good. This works like a charm.
But I had an idea. What about being more explicit and explicitly deleting the copy constructor of has_only_move_member
. So I wrote into the class has_only_move_member
:
has_only_move_member(const has_only_move_member&) = delete;
After that, the same code from above, there I moved objects into an map gives me an error:
/usr/include/c++/4.8/bits/stl_pair.h:134:45: error: use of deleted function ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’
Yeah of course it's deleted, but why is there such a gap between implicit and explicit delete?
I'm getting the same behaviour with g++ 4.8.2 and clang 3.4-rc1 on Debian with libstdc++ and recent apple-clang-llvm 4.0 on Mac OS X 10.9 with libc++
An implicitly defined copy constructor will copy the bases and members of an object in the same order that a constructor would initialize the bases and members of the object.
The copy constructor and copy-assignment operator are public but deleted. It is a compile-time error to define or call a deleted function. The intent is clear to anyone who understands =default and =delete . You don't have to understand the rules for automatic generation of special member functions.
When to delete copy constructor and assignment operator? Copy constructor (and assignment) should be defined when ever the implicitly generated one violates any class invariant. It should be defined as deleted when it cannot be written in a way that wouldn't have undesirable or surprising behaviour.
Copy Constructor is of two types:Default Copy constructor: The compiler defines the default copy constructor. If the user defines no copy constructor, compiler supplies its constructor. User Defined constructor: The programmer defines the user-defined constructor.
I already said this in the comment but since this is a correct answer I am reposting as one:
You added a custom constructor (even though it's a deleted one). Therefore the compiler won't auto generate a move constructor. The compiler then falls back to copying which (as you requested) it obviously can't do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With