2012-10-21 62 views
3

我想創建一個通用容器,它可以存儲類型爲Wrapper的異構對象< T>其中T可以是任何用戶定義的類型。我見過boost :: any和其他解決方案,但我不能重新調用函數foo()而不重新編寫(我不知道重寫哪種類型,關於T的信息會丟失。)它會回到原始類型。在C++中存儲特定模板的對象的通用容器

我該如何合理地實現一個通用容器/使用現有的通用容器來實現這一點?

template <typename T> 
class Wrapper{ 
public: 
    Wrapper(const T& a):o(a){}; 
    Wrapper(){}; 
    //public methods 
    void foo(){ 
    //do stuff 
    }; 
private: 
T o; 
}; 

class X{}; 
class Y{}; 

int main(){ 
    X x; 
    Y y; 

    A_GENERIC_CONTAINER generic_container; 
    // A_GENERIC_CONTAINER should be able to store 
    // any number of heterogeneous objects of type Wrapper<T> 
    // where T can be any user defined type. 

    generic_container.push_back(x); 
    generic_container.push_back(y); 

    auto it = generic_container.begin(); 
    auto end = generic_container.end(); 
    while(it != end){ 
    it->foo(); 
    ++it; 
    } 
} 
+0

也許這會有幫助。這是從自己的人:http://www.stroustrup.com/bs_faq2.html#containers –

+0

謝謝尼科斯,但問題是我不能使用任何或普通類的向量 - 包裝和包裝是2個不同的類總而言之 - 所以沒有運行時多態性。 –

+0

如果我下降到(無效*)我必須重鑄是包裝使用foo,我已經在T –

回答

4

最通用的方法是創建用於包裝一個基類,說BaseWrapper,並定義對然後在每個包裝類的實現的BaseWrapper純虛函數。通過專業化,每個Wrapper,Wrapper都可以有自己的實現。一旦你完成了,你可以使用一個智能指針的容器來使用Base Type,並在閒暇時使用它。

有一些可能的捷徑。例如,在你的例子中的簡單情況下,我會建議使用std::function。輔助函數有助於做到這一點。注意,這隻有在只有一個方法被調用時纔有效。我也建議讓你的包裝直接定義operator(),這樣你就不必使用綁定。

template<T> 
std::function<void()> wrap(const T& x) 
{ 
    return std::bind(&Wrapper<T>::foo, Wrapper<T>(x)); 
} 

int main(){ 
    X x; 
    Y y; 

    std::vector<std::function<void()> > generic_container; 
    // A_GENERIC_CONTAINER should be able to store 
    // any number of heterogeneous objects of type Wrapper<T> 
    // where T can be any user defined type. 

    generic_container.push_back(wrap(x)); 
    generic_container.push_back(wrap(y)); 

    auto it = generic_container.begin(); 
    auto end = generic_container.end(); 
    while(it != end){ 
    (*it)(); 
    ++it; 
    } 
} 

編輯:

我正在討論是一個非模板的基礎,從中派生所有的模板包裝的。這允許你調用你預定義的方法(並且必須由Wrapper實現),而不需要知道具體的包裝類型。

class Base 
{ 
    public: 
    virtual ~Base() {}; 
    virtual void foo() = 0; 
}; 

template <typename T> 
class Wrapper : public Base{ 
public: 
    Wrapper(const T& a):o(a){}; 
    Wrapper(){}; 
    //public methods 
    virtual void foo(){ 
    //do stuff 
    }; 
private: 
T o; 
}; 

int main(){ 
    X x; 
    Y y; 

    std::vector<std::shared_ptr<Base> > generic_container; 
    // A_GENERIC_CONTAINER should be able to store 
    // any number of heterogeneous objects of type Wrapper<T> 
    // where T can be any user defined type. 

    generic_container.push_back(std::make_shared<Wrapper<X>>(x)); 
    generic_container.push_back(std::make_shared<Wrapper<Y>>(y)); 

    auto it = generic_container.begin(); 
    auto end = generic_container.end(); 
    while(it != end){ 
    it->foo(); 
    ++it; 
    } 
} 
+0

:)謝謝戴夫。你的第二個捷徑解決了我的問題。但我想用BaseWrapper類來理解你的第一個解決方案。 –

+0

我如何創建智能指針基礎包裝的cotainer? vector >> wvec; –

+0

爲運營商()的技巧+1。 –

相關問題