如何聚合 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);
这是一个有点作弊的解决方案,所以正确的答案仍然有用。
根据 [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);
这是一个有点作弊的解决方案,所以正确的答案仍然有用。