专门化模板以包含模板模板
Specialising a template to include template templates
我正在自学c++模板编程,所以我的一些假设可能是错误的-如果你看到任何错误,请纠正我。
我试图使用STL列表作为一个函数的模板参数。该函数应该与各种数据类型一起使用,因此我在其原始声明中将该函数定义为template<class T>
而不是template<template<> class T>
。现在我想对它进行专门化,以支持模板类。
template<class T>
void function(T param)
{
// do something with T
}
template<template <class T, class Allocator> class listPlaceholder>
void function(std::list<T, Allocator> param)
{
// do something with every element in param (I actually need to know it's a list)
std::list<T, Allocator>::iterator current = param.begin();
std::list<T, Allocator>::iterator end = param.end();
do {
function<T>(*current);
} while (++current != end);
}
问题是,当我试图编译这个代码(在GCC下)它说T
和Allocator
没有在范围内定义。我的主要问题是"我如何专门化模板类?",其次,如果可能的话,"我如何提取模板模板参数?"
如前所述,我正在学习模板编程,因此欢迎明显的解决方案。
您需要声明这些参数
template<template <class T, class Allocator> class listPlaceholder,
class T, class Allocator>
void function(listPlaceholder<T, Allocator> param)
{
// do something with every element in param (I actually need to know it's a list)
typename listPlaceholder<T, Allocator>::iterator current = param.begin();
typename listPlaceholder<T, Allocator>::iterator end = param.end();
do {
function<T>(*current);
} while (++current != end);
}
在形式参数列表中使用的名称没有意义。实际上你还忘了使用listPlaceholder
。但我认为那是偶然的。
正如另一位发帖者所说,你还需要typename
关键字,因为名称是依赖名称。
为什么形式列表中的名称是无意义的,将其与函数指针进行比较:
void f(void (*p)(int t, int allocator), int t, int allocator) {
p(t, allocator);
}
void g(int a, int b) {
}
int main() {
f(&g, 0, 1);
}
重要的只是参数的类型,我也可以写void(*p)(int, int)
。在您的示例中,重要的是两个参数都是类型参数。所以你也可以把模板模板参数写成template<class, class> class listPlaceholder
,完全等价。
function
,而是用另一个模板重载了它。因此,两个function
是两个完全不同的函数模板。 g++
在这里实际上是正确的;您没有在此范围内声明T
或Allocator
。模板声明中有
template<template <class T, class Allocator> class listPlaceholder>
void function(std::list<T, Allocator> param)
表示"我在接受两个类作为参数的类模板上被参数化"。但是,这些参数的名称不能在模板体的任何地方访问。它们主要用作占位符,上面的模板声明相当于
template<template <class, class> class listPlaceholder>
void function(std::list<T, Allocator> param)
这类似于如果你要声明一个普通的c++函数,它将另一个函数作为实参,你不能访问形参的名称。例如,这是非法的:
void DoSomething(void function(int x, int y)) {
x = 5; // Error!
}
因为它相当于
void DoSomething(void function(int, int)) {
x = 5; // Error!
}
我相信你想做的是改变你的模板函数签名,像这样:
template<class T, class Allocator>
void function(std::list<T, Allocator> param)
这表示"此函数在两个类型上参数化。当作为参数提供类型和分配器参数化的std::list
时,该函数体可以将这些类型引用为T
和Allocator
。
使用typename
作为:
typename std::list<T, Allocator>::iterator current = param.begin();
typename std::list<T, Allocator>::iterator end = param.end();
这是因为iterator
是依赖名称,所以typename
是编译器需要的,这样它就可以知道iterator
实际上是一个类型,而不是一个静态值。
要详细了解这一点,请阅读此FAQ:
- 在哪里以及为什么我必须把"模板"answers";typename"关键字?
另外,你应该把你的函数模板写成:
template <class T, class Allocator>
void function(std::list<T, Allocator> param)
{
//code..
}
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 编译包含字符串的代码时遇到问题
- c++库的公共头文件中应该包含什么
- 将包含C样式数组的对象初始化为成员变量(C++)
- 是否需要删除包含对象的"pair"?
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 使用mongocxx驱动程序时包含头文件问题
- 如何在h文件中包含.o对象文件
- 在混合代码库中将C转换为C++时出现许多包含错误
- 是否可以对零模板参数进行模板专门化
- VS2017,C++包含目录与附加包含目录,子文件夹包含失败-但为什么
- cmath抛出错误C2062、C2059、C2143和C2447.cmath包含在矢量文件中
- 为什么您需要C++头文件的包含保护
- 无法在UE4中包含BP类到CPP类
- 为什么模数运算符不适用于该代码
- g++ 说函数不存在,即使包含正确的标头
- 在C++代码中包含opencv时,使用ctypes创建.so文件
- 专门化模板以包含模板模板