【问题标题】:Template class with template container带有模板容器的模板类
【发布时间】:2013-05-11 21:02:40
【问题描述】:

如何将具有不同容器的模板类(适配器)声明为模板参数? 比如我需要声明类:

template<typename T, typename Container>
class MyMultibyteString
{
    Container buffer;
    ...
};

我希望它基于矢量。如何使其硬定义? (防止有人写这样的声明MyMultibyteString&lt;int, vector&lt;char&gt;&gt;)。

另外,如何实现这样的构造:

MyMultibyteString<int, std::vector> mbs;

没有将模板参数传递给容器。

【问题讨论】:

    标签: c++ templates stl containers


    【解决方案1】:

    你应该使用模板模板参数

    template<typename T, template <typename, typename> class Container>
    //                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    class MyMultibyteString
    {
        Container<T, std::allocator<T>> buffer;
        // ...
    };
    

    这将允许您编写:

    MyMultibyteString<int, std::vector> mbs;
    

    这是一个正在编译的live example。编写上述内容的另一种方式可能是:

    template<typename T,
        template <typename, typename = std::allocator<T>> class Container>
    //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    class MyMultibyteString
    {
        Container<T> buffer; // <== No more need to specify the second argument here
        // ...
    };
    

    这里是对应的live example

    你唯一需要注意的是模板模板参数声明中的参数数量和类型必须与你要作为模板传递的相应类模板的定义中的参数数量和类型完全匹配参数,而不管其中一些参数可能具有默认值。

    例如,the class template std::vector accepts two template parameters(元素类型和分配器类型),尽管第二个具有默认值 std::allocator&lt;T&gt;。因此,你可以写:

    template<typename T, template <typename> class Container>
    //                             ^^^^^^^^
    //                             Notice: just one template parameter declared!
    class MyMultibyteString
    {
        Container<T> buffer;
        // ...
    };
    
    // ...
    
    MyMultibyteString<int, std::vector> mbs; // ERROR!
    //                     ^^^^^^^^^^^
    //                     The std::vector class template accepts *two*
    //                     template parameters (even though the second
    //                     one has a default argument)
    

    这意味着您将无法编写一个可以同时接受std::setstd::vector 作为模板模板参数的类模板,因为与std::vectorthe std::set class template accepts three template parameters 不同。

    【讨论】:

    • 多么棒的、彻底的答案。
    • @ScottJones:很高兴你发现它很有用 :)
    • @ScottJones 关于您的声明:This means that you won't be able to write one single class template that can accept both std::set and std::vector:可变参数模板能解决问题吗? stackoverflow.com/a/20499809/2436175
    • @Antonio:是的,这是可能的。不知道为什么我没想到:)
    • "这意味着您将无法编写一个可以同时接受std::setstd::vector 的类模板...因为std::set 接受三个模板参数" - 怎么样可变参数模板? template&lt; class... Args &gt;
    【解决方案2】:

    解决此问题的另一种方法是使用可变参数模板,您可以使用上面 cmets 中建议的任何容器,以下是实现:

    template<template <typename... Args> class Container,typename... Types>
    class Test
    {
        public:
        Container<Types...> test;
    
    };
    int main()
    {
      Test<std::vector,int> t;
      Test<std::set,std::string> p;
      return 0;
    }
    

    【讨论】:

    • 以及返回 Container&lt;Types...&gt; 的函数看起来如何?
    【解决方案3】:

    如果您查看 cplusplus.com 中的 listvector 的定义,例如,它们是:

    template < class T, class Alloc = allocator<T> > class list;
    

    template < class T, class Alloc = allocator<T> > class vector;
    

    所以这应该作为容器的类型,另一个模板参数是元素的类型。作为一个例子,这个程序将输出 3:

    #include <iostream>
    #include <list>
    using namespace std;
    
    template <template <typename...> typename C, typename T>
    struct Cont {
        C<T> info;
    };
    int main(void)
    {
        Cont<list, int> cont;
    
        cont.info.push_back(3);
        cout << cont.info.front() << endl;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-07
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多