Reputation: 811
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++
Upvotes: 7
Views: 2134
Reputation: 1149
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.
Upvotes: 10