Mario
Mario

Reputation: 811

implicit vs. explicit deleted copy constructor

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

Answers (1)

John5342
John5342

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

Related Questions