2015-06-22 186 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)。