我能想到的一个解决方案是利用这样一个事实,即没有上述继承的结构将很乐意发出默认的聚合初始化程序。因此,我将该结构与模板化包装器类型组合在一起。
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);
这是一个欺骗性的解决方案,因此正确的答案仍然有用。