簡體   English   中英

避免使用`operator <<`推遲“子”對象構造

[英]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<<執行相同的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)...)); }

你應該能夠使用你想要的語法。

(根據我之前的評論)。 我建議你構造base_ptr的base並將其提供給opertor<< (ideone link) 無需花哨或復雜。

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) ;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM