如何使用不同的容器声明模板类(适配器)作为模板参数? 例如,我需要声明class:
template<typename T, typename Container>
class MyMultibyteString
{
Container buffer;
...
};
我希望它基于矢量。如何使其明确定义? (以防止某人撰写此类声明MyMultibyteString<int, vector<char>>
)。
此外,如何实施这样的建设:
MyMultibyteString<int, std::vector> mbs;
没有将模板参数传递给容器。
答案 0 :(得分:71)
您应该使用模板模板参数:
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<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::set
和std::vector
作为模板模板参数的单个类模板,因为与std::vector
不同,{{3 }}
答案 1 :(得分:7)
解决此问题的另一种方法是使用可变参数模板,您可以使用上面评论中建议的任何容器,这里是实现:
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;
}
答案 2 :(得分:0)
如果您查看来自 cplusplus.com 的 list 和 vector 的定义,例如:
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;
}