41

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

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

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

此外,如何实施这样的建设:

MyMultibyteString<int, std::vector> mbs;

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

4

3 回答 3

80

您应该使用模板模板参数

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

这将允许您编写:

MyMultibyteString<int, std::vector> mbs;

这是一个编译的实时示例。编写上述内容的另一种方法可能是:

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
    // ...
};

这是相应的现场示例

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

例如,类模板std::vector接受两个模板参数(元素类型和分配器类型),尽管第二个具有默认值std::allocator<T>。正因为如此,你不能写:

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::vector类模板接受三个模板参数std::set

于 2013-05-16T20:05:27.823 回答
10

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

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;
}
于 2017-05-19T08:02:19.007 回答
0

如果您从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;
}
于 2020-04-27T15:30:04.760 回答