假设我有一个存储 std::vector
的容器对象多态 child 。
struct Child
{
Child(Parent& mParent) { /* ... */ }
virtual ~Child() { }
};
class Parent
{
private:
std::vector<std::unique_ptr<Child>> children;
template<typename T, typename... TArgs>
auto& mkChild(TArgs&&... mArgs)
{
// `static_assert` that `T` is derived from `Child`...
children.emplace_back(std::make_unique<T>(std::forward<TArgs>(mArgs)...));
return *children.back();
}
public:
template<typename T, typename... TArgs>
auto& add(TArgs&&... mArgs)
{
mkChild<T>(std::forward<TArgs>(mArgs)...));
return *this;
}
};
现在我可以使用 Parent
像这样上课:
int main()
{
Parent p;
p.add<Child1>(some_args1).add<Child2>(some_args2);
}
虽然这种语法实现了我想要做的事情(将子级添加链接到单个父级),但我发现它很难阅读,尤其是在我的实际用例中。
我真的很想用 operator<<
反而。但我想不出一种方法来构建 child 。
// Desired syntax
int main()
{
Parent p;
p << mk<Child1>(some_args1) << mk<Child2>(some_args2);
}
请注意我从未在 mk
中指定父级功能。
不想说mk<Child1>(p, some_args1)
.编译器应该找出 p
来自 operator<<
的链接.
有什么方法可以实现这个 mk
函数生成代码等于通过 .add<T>(...)
生成的代码链接?
我设法实现它的唯一方法是使用一个中间人结构来保存子类的构造可变参数。
template<typename T, typename... TArgs> struct DeferCtor
{
std::tuple<TArgs...> ctorArgs;
};
然后 operator<<(DeferCtor<T, TArgs...>&)
将处理内部对象的构造 Parent
.
有没有办法避免这一步,同时仍然具有所需的语法? (不在 mk
函数中传递父实例。)
最佳答案
您并没有真正在现有代码中创建对象——您是在堆上使用 unique_ptr
创建子对象然后移动那个unique_ptr
成 parent 。你可以对你的 operator<<
做同样的事情如果您只是将其定义为采用 unique_ptr
:
Parent &Parent::operator<<(std::unique_ptr<Child> ch) {
children.emplace_back(std::move(ch)); }
现在假设您的 mk
global 函数本质上只是 make_unique
的别名:
template<typename T, typename... TArgs>
std::unique_ptr<T> mk(TArgs&&... mArgs) {
return std::make_unique<T>(std::forward<TArgs>(mArgs)...)); }
您应该能够使用您想要的语法。
关于c++ - 避免使用 "child"延迟 `operator<<` 对象构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29063926/