如何删除 C++ 中 class 的所有隐式(默认)方法?

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

C++编译器在某些条件下为class添加隐式默认构造函数、复制构造函数、析构函数、转换运算符、赋值运算符等以及其他隐式方法。

如何以最短的方式disable/delete所有可能的隐式方法?

我不希望我的 class 不可复制,我只想禁用这些默认方法,以便编译器抛出编译错误,然后我自己实现它们。我只想过度控制,这样编译器就不会对我的 class.

做任何静默工作

例如我可以做下一件事(这只是一个虚拟的例子,在现实生活中我可以有任何复杂的class):

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

但这是很长的路要走,而且我可能会忘记删除一些方法签名,我需要删除所有方法签名。所以我自己从头开始重新实现所有方法。

而且我需要查看其他代码 needs/uses 和我尚未实现的所有方法的错误,而不是编译器默默地为我实现这些方法。

此外,如果我像上面示例中那样删除默认方法,我如何确定没有其他静默创建的方法?在线是否有编译器静默创建的 100% 所有标准方法的列表?

您可能会选择混合方法。定义繁琐class一次

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) {}
};

然后从中继承:

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

额外的 token 类型允许派生 classes 来实现 other 构造函数,例如 C::C(int) (甚至是用户-提供 C::C()).

See it live.

最短的选择可能是拥有一个可重复使用的虚拟底座 class:

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

继承privately就够了;

class Test : private NoSpecialMember {};

结果如下:

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>);

定义 helper 并将其用作 class 应禁用的字段:

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

class Foo
{
private:
    DisableCopyAssign dummy;
};

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