为什么我需要在g ++中使用typedef typename,而不是VS? [英] Why do I need to use typedef typename in g++ but not VS?

查看:89
本文介绍了为什么我需要在g ++中使用typedef typename,而不是VS?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一段时间,因为GCC抓住了我这个,但它只是发生了今天。但我从来没有理解为什么GCC需要typedef类型名称的模板,而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因为它想要这样:

 模板< 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 = container.find(key);
return iter!= container.end();
}

注意:这不是我使用的实际函数,


解决方案

标准需要类型名称。模板编译需要两步验证。在第一遍中,编译器必须验证模板语法,而不实际提供类型替换。在此步骤中,假设std :: map :: iterator是一个值。如果它表示类型,则需要typename关键字。



为什么这是必要的?在替换实际的KEY和VALUE类型之前,编译器不能保证模板不是专门的,并且专业化不会将 iterator 关键字重新定义为其他形式。



您可以使用此代码检查:

  class X {}; 
template< typename T>
struct Test
{
typedef T value;
};
模板<>
struct Test< X>
{
static int value;
};
int Test< X> :: value = 0;
template< typename T>
void f(T const&)
{
Test< T> :: value; //在第一遍期间,测试< T> ::值被解释为值
}
int main()
{
f(5) //编译错误
X x; f(x); // compiles fine f:Test< T> :: value is an integer
}

最后一个调用失败,并显示一个错误,指示在f()Test :: value的第一个模板编译步骤被解释为一个值,但是类型X的Test<>模板的实例化产生一个类型。


It had been a while since GCC caught me with this one, but it just happened today. But I've never understood why GCC requires typedef typename within templates, while VS and I guess ICC don't. Is the typedef typename thing a "bug" or an overstrict standard, or something that is left up to the compiler writers?

For those who don't know what I mean here is a sample:

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();
}

The above code compiles in VS (and probably in ICC), but fails in GCC because it wants it like this:

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 = container.find(key);
    return iter!=container.end();
}

Note: This is not an actual function I'm using but just something silly that demonstrates the problem

解决方案

The typename is required by the standard. Template compilation requires a two step verification. During the first pass the compiler must verify the template syntax without actually supplying the type substitutions. In this step, std::map::iterator is assumed to be a value. If it does denote a type, the typename keyword is required.

Why is this necessary? Before substituing the actual KEY and VALUE types, the compiler cannot guarantee that the template is not specialized and that the specialization is not redefining the iterator keyword as something else.

You can check it with this code:

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
}

The last call fails with an error indicating that during the first template compilation step of f() Test::value was interpreted as a value but instantiation of the Test<> template with the type X yields a type.

这篇关于为什么我需要在g ++中使用typedef typename,而不是VS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆