具有模板化类参数的模板化函数

templated function with an argument that is a templated class

本文关键字:函数 参数      更新时间:2023-10-16

我意识到有很多类似的问题,但我找不到任何可以解决我的问题(阅读:我没有真正理解答案,因此我可以将其应用于我的情况)

我有以下功能:

void printVariable(map<string, bool*>::iterator it)
{
   cout << it->first << " " << *(it->second) << endl;
}

现在,如果我有map<string, bool*> mapping我可以执行以下操作:printVariable(mapping.begin());

这行得通,现在我也有一个map<string, int*>并希望能够做同样的事情,所以我想我更改了 printVariable 函数:

template <typename T>
void printVariable(map<string, T*>::iterator it)
{
   cout << it->first << " " << *(it->second) << endl;
}

但是,这会产生编译错误(gcc):

error: variable or field 'printVariable' declared void
error: expected ')' before 'it'

我想我可以通过重载函数来轻松解决此问题。但我想知道为什么上述方法不起作用。

Edit2:删除了声称正确解决方案错误的文字

你必须说typename来消除依赖名称的歧义:

template <typename T>
void printVariable(typename map<string, T*>::iterator it)
//                 ^^^^^^^^

但是,请注意,这不是一个可推导的上下文,因此这种形式不是很方便。

更好的是,只需将整个迭代器设置为模板参数:

template <typename Iter>
void printVariable(Iter it)
{ /* ... */ }

这样,您还可以捕获具有非标准比较器或分配器的地图,以及无序地图等。


这里有一个简单的思想实验,说明为什么在第一种情况下你没有可推导的上下文:在下面的foo召唤中,T应该如何推导?

template <typename T> void foo(typename Bar<T>::type);
template <typename T> struct Bar { typedef char type; };
template <> struct Bar<int>      { typedef int type; };
template <> struct Bar<double>   { typedef int type; };
foo(10); // What is T?