c++ - 避免使用 "child"延迟 `operator<<` 对象构造

标签 c++ constructor operator-overloading variadic-templates c++14

假设我有一个存储 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/

相关文章:

c++ - std::vector ctor 在类外编译,但不在类内?

c++ - 将运算符作为函数模板参数传递

C++ 运算符重载和关联的命名空间

c++ - 在链表前面添加节点

C++ 隐式函数调用

来自不同源文件的c++命名空间

c++ - 什么时候调用 const operator[],什么时候调用 non-const operator[]?

c++ - 如何在 Visual Studio 中为聚合激活 (N)RVO?

c++ - 在构造函数中调用类成员的构造函数

c++ - 模板类的专用构造函数