如何聚合从虚拟类型继承的结构init



根据[dcl.init.agr],如果init具有(除其他外(虚拟函数,包括从具有虚拟析构函数的类型继承,则我无法聚合init类型。然而,我希望避免编写大量的样板构造函数。

MWE:

struct Base {
virtual ~Base() {}
};
struct Derived : Base {
int i;
};
int main() {
Derived d1{42}; // not allowed in this fashion
Derived d2{{},42}; // also not allowed
}

在我的设置中,我有很多像Derived这样的类型,它们都是带有许多成员的普通结构(不一定是琐碎的/pod(,除了,因为它们必须从Base继承。

有没有一种方法可以避免为所有的Derived(int i) : Base(), i(i) {}构造函数编写?

我能想到的一个解决方案是利用这样一个事实,即没有以上继承的结构将很乐意发出默认的聚合初始化程序。因此,我将结构与模板化包装器类型组合在一起。

template <typename T>
struct BaseWrapper : Base, T {
BaseWrapper(T data) : Node(), T(data) {}
BaseWrapper() = delete;
BaseWrapper(BaseWrapper const&) = default;
BaseWrapper(BaseWrapper&&) = default;
BaseWrapper& operator=(BaseWrapper const&) = default;
BaseWrapper& operator=(BaseWrapper&&) = default;
static T const& cast(Base const& b) {
return static_cast<T const&>(static_cast<BaseWrapper<T> const&>(b));
}
static T& cast(Base& b) {
return static_cast<T&>(static_cast<BaseWrapper<T>&>(b));
}
};

由于我使用Derived类型作为共享指针,因此有一个小的方便函数:

template <typename T, typename... Args>
inline std::shared_ptr<BaseWrapper<T>> make_bw(Args&&... args) {
return std::make_shared<BaseWrapper<T>>(T{std::forward<Args>(args)...});
}

允许我们在不需要对象内部专用构造函数的情况下创建对象:

struct Derived { // note the missing : Base
int i;
};
auto p = make_bw<Derived>(42);

这是一个有点作弊的解决方案,所以一个正确的答案仍然有用。

最新更新