C++ 带有模板容器的模板类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16596422/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Template class with template container
提问by DuXeN0N
How can I declare template class (adaptor) with different containers as template arguments? For example, I need to declare class:
如何将具有不同容器的模板类(适配器)声明为模板参数?例如,我需要声明类:
template<typename T, typename Container>
class MyMultibyteString
{
Container buffer;
...
};
And I want it to my based on vector. How to make it hard-defined? (to prevent someone from writing such declaration MyMultibyteString<int, vector<char>>
).
我希望它基于向量。如何让它硬定义?(防止有人写这样的声明MyMultibyteString<int, vector<char>>
)。
Moreover, how to implement such construction:
此外,如何实现这样的构建:
MyMultibyteString<int, std::vector> mbs;
without passing template argument to container.
不将模板参数传递给容器。
回答by Andy Prowl
You should use template template parameters:
您应该使用模板模板参数:
template<typename T, template <typename, typename> class Container>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class MyMultibyteString
{
Container<T, std::allocator<T>> buffer;
// ...
};
This would allow you to write:
这将允许您编写:
MyMultibyteString<int, std::vector> mbs;
Here is a compiling live example. An alternative way of writing the above could be:
这是一个编译现场示例。编写上述内容的另一种方法可能是:
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
// ...
};
And here is the corresponding live example.
这是相应的现场示例。
The only thing you have to pay attention to is that the number and type of arguments in the template template parameter declaration must match exactly the number and type of arguments in the definition of the corresponding class template you want to pass as a template argument, regardless of the fact that some of those parameters may have default values.
您唯一需要注意的是,模板模板参数声明中的参数数量和类型必须与您要作为模板参数传递的相应类模板的定义中的参数数量和类型完全匹配,无论事实上,其中一些参数可能具有默认值。
For instance, the class template std::vector
accepts two template parameters(the element type and the allocator type), although the second one has the default value std::allocator<T>
. Because of this, you could notwrite:
例如,类模板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)
This means that you won't be able to write one single class template that can accept both std::set
and std::vector
as a template template parameter, because unlike std::vector
, the std::set
class template accepts threetemplate parameters.
这意味着你将不能写一个单独的类模板,既可以接受std::set
,并std::vector
作为模板的模板参数,因为不像std::vector
,在std::set
类模板接受3个模板参数。
回答by Kapil
Another approach to solve this is by using variadic templates and with that you can use any container as suggested in comments above and here is the implemenation :
解决此问题的另一种方法是使用可变参数模板,您可以使用上面评论中建议的任何容器,这是实现:
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;
}
回答by baz
If you look at the definitions of listand vectorfrom cplusplus.com, for example they are:
如果你看一下的定义列表和向量自cplusplus.com,例如它们分别是:
template < class T, class Alloc = allocator<T> > class list;
and
和
template < class T, class Alloc = allocator<T> > class vector;
So this should go as the type of the container, the other template parameter is the type of the elements. As an example this program will output 3:
所以这应该作为容器的类型,另一个模板参数是元素的类型。作为示例,该程序将输出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;
}