C++模板模板

C++ template template

本文关键字:C++      更新时间:2023-10-16

我正试图通过实现一个通用容器类来理解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!
    }

上面的代码生成一条编译器错误消息。错误消息为:

"template-template参数的模板参数与其对应的模板模板参数不同存储aStack1;

我不知道为什么。怎么了?

您的问题是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

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; 

作为@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这样的一些编译器在这方面有问题,否则就会失败,因为它们需要两个模板参数,请参见此处的示例)。

相关文章:
  • 没有找到相关文章