2015-06-22 96 views
3

我想通過實現一個通用的容器類來理解C++模板模板。以下是代碼:C++模板模板

using namespace std; 

    template <typename T, template <typename STORETYPE> class Container> 
    class Store { 
    public: 
     ~Store() {}; 
     Store() {}; 
     void someFunc(const T &) {}; 
     //... 
    private: 
     Container<T> storage; 
    }; 




    int main(int argc, char *argv[]) 
    { 
     Store<int,deque> myStore; // error here, won't compile! 
    } 

上面的代碼會生成一個編譯器錯誤消息。該錯誤信息是:

「模板的模板參數具有比其相應的模板的模板參數 商店aStack1不同的模板參數;

我不知道爲什麼什麼問題

+1

如果您只通過deque ,您可以使用deque特性來獲取其內部類型(deque :: value_type),而不是爲容器提供兩個模板參數T和Container。 – Robinson

回答

6

你的問題是,std::deque? (以及其他標準容器)不僅僅是一個模板參數,還可以指定一個分配器函數類型來使用。

如果你不關心這些額外的參數,你可以只需要一個可變模板模板板用自己的方式:

template <typename T, template <typename...> class Container> 
//        variadic ^^^ 
class Store { 

如果你也想支持的可選參數傳遞給你的容器類型,你可以把和他們這樣的:

template <template <typename ...> class Container, typename T, typename... ContainerArgs> 
class Store { 
    //... 
    Container<T,ContainerArgs...> storage; 
}; 

然後實例如下所示:

Store<deque,int> myStore; 
Store<deque,int,MyIntAllocator> mySpecialStore; 

然而,你可能只是想利用專業化提取模板參數:

template <typename Container> 
class Store; 

template <template <typename...> class ContainerType, typename T, typename... OtherArgs> 
class Store<ContainerType<T,OtherArgs...>> 
{ 
    //... 
}; 

這將讓客戶端代碼實例是這樣的:

Store<deque<int>> myStore; 
Store<deque<int,MyIntAllocator>> mySpecialStore; 
Store<T> myOtherStore; //where T is some specialized container type 
+0

但請注意,在第一種情況下,某些編譯器(例如MSVC)會拒絕'Container '的實例化,因爲它們預期有兩個針對'std :: deque'的模板參數。 – davidhigh

1

std::deque被定義爲

template <class T, class Allocator = allocator<T> > class deque; 

所以,你應該改變Store定義匹配:

template <typename T, template <typename...> class Container> 
class Store { 

但實際上,您甚至不需要此模板參數。你甚至可以達到更一般的情況剛好路過的容器類型作爲參數,因此,例如Storage甚至會std::map支持:

template <typename Container> 
class Store { 
public: 
    using value_type = typename Container::value_type; 
    ~Store() {}; 
    Store() {}; 
    void someFunc(const value_type&) {}; 
    //... 
private: 
    Container storage; 
}; 

Store<std::map<int, float>> myStore; 
+0

相反value_type'的',人們也可以使用該結果型'操作符[]',即使用'= VALUE_TYPE的decltype(標準:: declval ().operator [](爲size_t {}))'。這可能會減少對Container的限制。 – davidhigh

+0

@davidhigh所有的標準容器都有'value_type',但並非全部都有'operator []'。 –

1

作爲替代由@TartanLlama答案,你也可以使用別名deque

template<typename T> 
using deque_alias = deque<T>; 

int main(int argc, char *argv[]) 
{ 
    Store<int,deque_alias> myStore; // now it will compile! 
} 

隨後也默認模板參數(這裏std::allocator<T>)的正確使用。 (像MSVC這樣的編譯器有問題,否則會失敗,因爲他們期望兩個模板參數,例如參見here)。