2

根据[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除了它们必须继承自Base.

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

4

1 回答 1

0

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

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

这是一个欺骗性的解决方案,因此正确的答案仍然有用。

于 2020-03-07T17:55:08.143 回答