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

How can I aggregate init a struct that inherits from a virtual type?

根据 [dcl.init.aggr] 我无法聚合 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,它们都是具有多个成员的普通结构(不一定 trivial/pod)except 因为他们必须继承自 Base.

有没有办法避免为所有这些编写 Derived(int i) : Base(), i(i) {} 构造函数?

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

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

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