在 C++20 中,聚合不能有用户声明或继承的构造函数(因此您不能将它们声明为删除)。 那么有没有办法让结构仍然是一个聚合,但不可复制?
根据 aggregates 上的规则,您不能在聚合本身上删除构造函数,而是在基类上,例如:
struct bar{
// having the defaulted constructor is required for C++20 aggregate initialization to work
bar() = default;
// prevents copy and deletes other constructors
bar(const bar&) = delete;
};
struct foo : bar{
int a;
};
然后您可以使用聚合语法对其进行初始化:
foo b {{}, 1};
// or
foo c { .a = 1};
这将(大部分)正常工作:工作示例
然而,存在明显的权衡,因为添加继承会破坏某些功能。例如:https://godbolt.org/z/P8Ea61oh3
std::optional<foo> e(std::in_place, {}, 1);
会坏的。
添加一个不可复制的基数是可行的,但它的缺点是基数是first,所以它会扰乱paren初始化。做完全相同的想法,但把它放在last更好:
struct noncopyable {
noncopyable() = default;
noncopyable(noncopyable&&) = default;
noncopyable& operator=(noncopyable&&) = default;
};
struct foo {
int i;
// ... more members here ...
[[no_unique_address]] noncopyable _ = {};
};
从聚合中删除 any 用户声明的构造函数的论文是 P1008。非常不幸的是,我们基本上绕了一个圈——在 C++03 中,为了使类不可复制,您将复制构造函数声明为私有的。在 C++11 中,我们可以明确地删除它,这使得代码中发生的事情更加清晰。在 C++20 中,我们取消了聚合的能力,所以现在我们又回到了奇怪的恶作剧。