带有参数的模板化函数,它是一个模板化的类

use*_*914 0 c++ templates

我意识到有很多类似的问题,但我找不到任何可以解决我的问题(读:我没有真正理解答案,所以我可以将它应用到我的案例中)

我有以下功能:

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

现在,如果我有,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;
}
Run Code Online (Sandbox Code Playgroud)

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

error: variable or field 'printVariable' declared void
error: expected ')' before 'it'
Run Code Online (Sandbox Code Playgroud)

我想我可以通过重载函数来解决这个问题.但我想知道为什么以上不起作用.

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

Ker*_* SB 5

您必须说typename明确依赖名称的歧义:

template <typename T>
void printVariable(typename map<string, T*>::iterator it)
//                 ^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

但请注意,这不是可推断的上下文,因此这种形式并不十分方便.

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

template <typename Iter>
void printVariable(Iter it)
{ /* ... */ }
Run Code Online (Sandbox Code Playgroud)

这样,您还可以使用非标准比较器或分配器以及无序地图等捕获地图等.


这是一个简单的思想实验,为什么你在第一种情况下没有可推导的背景:如何T在下面的调用中推断出foo

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?
Run Code Online (Sandbox Code Playgroud)

  • @ user1302914:你不能*演绎*第一个,因为它不是一个可推导的上下文.这就是为什么你应该更喜欢第二个版本. (2认同)