避免使用"运算符<<推迟"child"对象构造
Avoiding to defer "child" object construction with `operator<<`
假设我有一个容器对象,它存储了多态子项的std::vector
。
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<<
。但是我想不出一种方法来构建孩子。
// Desired syntax
int main()
{
Parent p;
p << mk<Child1>(some_args1) << mk<Child2>(some_args2);
}
请注意,我从未在 mk
函数中指定父级。
我不想说mk<Child1>(p, some_args1)
.编译器应该从operator<<
的链接中找出p
。
有什么方法可以实现这个mk
函数生成与通过.add<T>(...)
链接生成的代码相同的代码?
我设法实现这一点的唯一方法是使用中间人结构,该结构保存子类的构造可变参数。
template<typename T, typename... TArgs> struct DeferCtor
{
std::tuple<TArgs...> ctorArgs;
};
然后operator<<(DeferCtor<T, TArgs...>&)
将处理对象在Parent
内部的构造。
有没有办法避免此步骤,同时仍然具有所需的语法?(不在 mk
函数中传递父实例。
你并没有真正在现有代码中就地创建对象 - 你使用unique_ptr
在堆上创建子对象,然后将该unique_ptr
移动到父对象中。 你可以对你的operator<<
做同样的事情,如果你只是把它定义为采取一个unique_ptr
:
Parent &Parent::operator<<(std::unique_ptr<Child> ch) {
children.emplace_back(std::move(ch)); }
现在假设你的mk
全局函数本质上只是make_unique
的别名:
template<typename T, typename... TArgs>
std::unique_ptr<T> mk(TArgs&&... mArgs) {
return std::make_unique<T>(std::forward<TArgs>(mArgs)...)); }
您应该能够使用所需的语法。
(基于我之前的评论)。我建议你构建碱基的unique_ptr并将其提供给opertor<<
(ideone链接)。无需花哨或复杂。
using namespace std;
using mk = make_unique;
#include <memory>
#include <iostream>
class B {};
class D : public B {};
class E : public B {};
class A {
public:
A & operator << ( std::unique_ptr<B> bp){
std::cout << " added a value " << std::endl;
// children.push_back(move(bp));
return *this;
}
};
int main() {
// your code goes here
A a;
a << mk<D>( .. some argument ) << mk<E>( other arguments) ;
}
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- 更改"child's parent's style sheet"时如何将孩子的样式表重置为 Qt 默认样式表?
- 如何显式调用运算符<<
- C++:无法将参数1从Child非模板类转换为Parent模板类
- qt get child (Callout) from QChart
- 传递 boost::filesystem::p ath 到 boost::p rocess::child 会导致 Win
- 将子类实例保存在父类型变量中并通过父变量使用 Child 函数?
- 如何确保我们从 boost::child 进程中读取所有行
- 模板操作员&lt;未打电话
- C / CUDA中的模板方法是3个角括号(&lt;&lt;&lt;)
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- C 建造者Clang STD :: Sill,找不到超载的操作员&lt;
- 为什么STD :: MAP需要操作员&lt;以及我如何写一个
- 为什么“操作员”需要const但不是为“运营商&lt;”
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- CMake: Hide -WShadow global compile flag for child target