How to delete all implicit (default) methods of class in C++?

Viewed 435

C++ compiler in certain conditions for class adds implicit default constructor, copy constructor, destructor, conversion operators, assignment operators, etc. And other implicit methods.

How do I disable/delete all possible implicit methods in shortest way possible?

I don't want my class to be un-copyable, I want just these default methods to be disabled so that compiler throws compile error and I implement them by myself. I just want to have over-control, so that compiler doesn't do any silent work about my class.

For example I can do next thing (this is just a dummy example, in real life I can have any complex class):

class C {
private:
    C() = delete;
    C(C const & other) = delete;
    C & operator = (C const & other) = delete;
};

But this is long way, also I can forget deleting some of methods signatures and I need to delete all of them. So that I reimplement all methods from scratch by myself.

And I need to see errors for all methods that other code needs/uses and that I have not yet implemented, instead of compiler silently implementing those methods for me.

Also if I delete default methods like I did above in my example, how can I be sure that there are no other silently created methods? Is there online a list of 100% all standard methods created silently by compiler?

3 Answers

You may go for a mixin approach. Define the cumbersome class once

class DeleteAllSpecialMemebers {
private:
    DeleteAllSpecialMemebers() = delete;
    DeleteAllSpecialMemebers(DeleteAllSpecialMemebers const &) = delete;
    DeleteAllSpecialMemebers & operator = (DeleteAllSpecialMemebers const &) = delete;
    DeleteAllSpecialMemebers(DeleteAllSpecialMemebers &&) = delete;
    DeleteAllSpecialMemebers & operator = (DeleteAllSpecialMemebers &&) = delete;
protected:
    struct token { explicit token() = default; };
    DeleteAllSpecialMemebers(token) {}
};

Then inherit from it:

class C : private DeleteAllSpecialMemebers{
public:
    C(int) : DeleteAllSpecialMemebers(token{}) {}
};

The extra token type is to allow deriving classes to implement other constructors, such as C::C(int) (or even a user-provided C::C()).

See it live.

The shortest option might be to have a reusable dummy base class:

struct NoSpecialMember {
    NoSpecialMember(const NoSpecialMember&) = delete;
    NoSpecialMember& operator=(const NoSpecialMember&) = delete;
    NoSpecialMember(NoSpecialMember&&) = delete;
    NoSpecialMember& operator=(NoSpecialMember&&) = delete;
    ~NoSpecialMember() = default;
};

It's sufficient to inherit privately;

class Test : private NoSpecialMember {};

with the following result:

static_assert(!std::is_copy_constructible_v<Test>);
static_assert(!std::is_copy_assignable_v<Test>);
static_assert(!std::is_move_constructible_v<Test>);
static_assert(!std::is_move_assignable_v<Test>);

Define helper and use it as field of class where it should be disabled:

struct DisableCopyAssign
{
    DisableCopyAssign(char){}
    DisableCopyAssign(const DisableCopyAssign&) = delete;
    DisableCopyAssign(DisableCopyAssign&&) = delete;
};

class Foo
{
private:
    DisableCopyAssign dummy;
};

https://gcc.godbolt.org/z/ce8sjq

Related