2011-01-21 59 views
13

我有一段時間沒有使用C++的高級特性,並且正在刷新我的C++知識。 話雖如此,特質和基於策略的編程的概念是我從未真正管理讓我的頭靠近。這個類的C++特徵示例

我想改變這一點。我正在寫一個通用容器。我想執行一個策略,容器將只存儲從特定基類派生的類。這是因爲當嘗試訪問向量邊界外的項目時,容器返回無效對象(而不是拋出)。

template <class T> 
class GenericContainer 
{ 
private: 
    typedef std::vector<T> TypeVect; 
    void addElement(const T& elem); 

    TypeVect m_elems; 

public: 
    unsigned int size() const; 
    T& elementAt(const unsigned int pos); 
    const T elementAt(const unsigned int pos) const; 
}; 

我該如何使用traits來限制這個泛型容器只包含類'ContainerItem'的子類呢?

+1

此模板的標準(C++ 0x)工具是`template struct is_base_of;` – 2011-01-21 16:35:01

+0

is_base_of也可以在boost和tr1中找到,用於缺少C++ 0x支持的編譯器 – Grizzly 2011-01-22 13:03:04

回答

12

您可以使用一個小IsDerivedFrom模板只能在情況下被實例化一個給定類型「d」繼承了另一種類型的「B」(這種實現是從nice Guru Of The Week article拍攝):

template<typename D, typename B> 
class IsDerivedFrom 
{ 
    static void Constraints(D* p) 
    { 
    B* pb = p; // this line only works if 'D' inherits 'B' 
    pb = p; // suppress warnings about unused variables 
    } 

protected: 
    IsDerivedFrom() { void(*p)(D*) = Constraints; } 
}; 

// Force it to fail in the case where B is void 
template<typename D> 
class IsDerivedFrom<D, void> 
{ 
    IsDerivedFrom() { char* p = (int*)0; /* error */ } 
}; 

您現在可以簡單地初始化IsDerivedFrom模板使用繼承:

template <class T> 
class GenericContainer : public IsDerivedFrom<T, ContainerItem> 
{ 
    ... 
}; 

如果T繼承ContainerItem此代碼僅編譯。

5

您可以使用boost::mpl來強制執行此操作,以在編譯時斷言某個類型從基地繼承。

的 「滾你自己」 是相當簡單:

template <typename D, typename B> 
class is_derived_from { 
    class No { }; 
    class Yes { No no[2]; }; 

    static Yes Test(B*); 
    static No Test(...); 
public: 
    enum { inherits = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) }; 
    static bool is_derived() { return inherits; } 
}; 

我想這來自GoTW原本。所有你需要的是一個合適的斷言機制(編譯時間可能更好)。通常的技巧是創建一個宏,使負數大小的數組無法通過斷言或1傳遞它。

+0

現在,我想要一個不涉及BOOST的解決方案。我想知道如何「滾動我自己的」 – skyeagle 2011-01-21 16:20:03

3

我想你正在尋找概念檢查。這即將被內置到C++ 0x,但它已被推遲。 Boost庫contain a library用於管理概念,但它遠非語法糖果。

備註:注意容器中的物體切片。如果你想允許基類和派生類都存儲在容器中,請使用指針而不是對象本身。

2

類型特徵和基於策略的編程是不同的主題。類型特徵添加關於不能包含額外信息(任何內建)的現有類型和類型的新信息。基於策略的設計是一種設計類的方法,以便您可以用各種方式組裝它們以創建不同的行爲;它是一種編譯時狀態模式。