自从 GCC 发现我有这个问题以来已经有一段时间了,但它今天才发生。但我一直不明白为什么 GCC 需要在模板中使用 typedef typename,而 VS 和我猜 ICC 不需要。 typedef typename 是一个“bug”还是一个过于严格的标准,或者是留给编译器编写者的东西?
对于那些不明白我的意思的人,这里有一个示例:
template<typename KEY, typename VALUE>
bool find(const std::map<KEY,VALUE>& container, const KEY& key)
{
std::map<KEY,VALUE>::const_iterator iter = container.find(key);
return iter!=container.end();
}
上面的代码在 VS 中编译(也可能在 ICC 中),但在 GCC 中失败,因为它希望这样:
template<typename KEY, typename VALUE>
bool find(const std::map<KEY,VALUE>& container, const KEY& key)
{
typedef typename std::map<KEY,VALUE>::const_iterator iterator; //typedef typename
iterator iter = container.find(key);
return iter!=container.end();
}
注意:这不是我正在使用的实际函数,而只是演示问题的一些愚蠢的函数。
类型名称是标准所要求的。模板编译需要两步验证。在第一遍期间,编译器必须验证模板语法,而不实际提供类型替换。在此步骤中,std::map::iterator 被假定为一个值。如果它确实表示类型,则需要 typename 关键字。
为什么这是必要的?在替换实际的 KEY 和 VALUE 类型之前,编译器不能保证模板没有特化,并且特化没有定义iterator关键字作为其他东西。
您可以使用以下代码进行检查:
class X {};
template <typename T>
struct Test
{
typedef T value;
};
template <>
struct Test<X>
{
static int value;
};
int Test<X>::value = 0;
template <typename T>
void f( T const & )
{
Test<T>::value; // during first pass, Test<T>::value is interpreted as a value
}
int main()
{
f( 5 ); // compilation error
X x; f( x ); // compiles fine f: Test<T>::value is an integer
}
最后一次调用失败并显示错误,指示在 f() Test::value 的第一个模板编译步骤期间被解释为值,但使用类型 X 实例化 Test 模板会生成类型。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)