我得到了一个派生自struct A
的struct B
。
struct A{
int a;
};
struct B : public A{
int b;
};
有没有一种直接的方法可以在不提供构造函数的情况下初始化 B
类型的对象,比如说使用初始化程序列表?
更多见解:
我有两个struct
用于在线程之间传递数据;第二个保存与第一个相同的数据,并添加了一些同步变量。我可以使第一个struct
成为第二个的数据成员,或者只是复制第二个struct
中的数据成员的声明,以轻松使用初始值设定项列表;但我认为在这个特定的应用程序中,第二个struct
扩展第一个在逻辑上会更正确。
没有一个非常简洁的解决方案,但至少有一个解决方案:
#include <type_traits>
#include <utility>
struct B : A
{
int b;
template <typename ...Args,
typename = typename std::enable_if<
std::is_constructible<A, Args&&...>::value>
B(int x, Args &&... args)
: b(x), A(std::forward<Args>(args)...)
{ }
};
此解决方案并不完全简短,但它是通用的。B
的新构造函数仅存在于那些有意义的专业中,这要归功于启用 - if SFINAE,因此B
恰好是可构造的。
这里还有一个我没有解决的危险,即新构造函数应该多explicit
。理想情况下,它应该像匹配A
构造函数一样显式,但这有点难以以编程方式检测(就像在 N4064 中为对和元组所做的那样)。
您不能对B
使用聚合初始化,因为它不是聚合,根据 [dcl.init.aggr]/1:
聚合是一个数组或类(第 9 条),没有用户提供的构造函数 (12.1),没有私有或 受保护的非静态数据成员(条款 11)、没有基类(条款 10)和没有虚函数 (10.3)。
更新:Kerrek SB 使用模板构造函数提供了一个很好的解决方案,但如果您愿意,您可以为 B
添加非常简单的非模板构造函数:
struct B : public A{
int b;
B(const A& a_, int b_) : A(a_), b(b_) {}
};
并将其与一对额外的牙套一起使用:
B b {{3}, 5};