当前位置:  开发笔记 > 编程语言 > 正文

为什么我需要在g ++中使用typedef typename而不是VS?

如何解决《为什么我需要在g++中使用typedeftypename而不是VS?》经验,为你挑选了2个好方法。

自从海湾合作委员会抓住我这个问题已经有一段时间了,但它刚刚发生在今天.但是我从来没有理解为什么GCC在模板中需要typedef typename,而VS和我猜ICC没有.typedef typename是一个"bug"还是一个严格的标准,还是留给编译器编写者的东西?

对于那些不知道我的意思的人来说,这是一个样本:

template
bool find(const std::map& container, const KEY& key)
{
    std::map::const_iterator iter = container.find(key);
    return iter!=container.end();
}

上面的代码在VS(可能在ICC中)编译,但在GCC中失败,因为它想要这样:

template
bool find(const std::map& container, const KEY& key)
{
    typedef typename std::map::const_iterator iterator; //typedef typename
    iterator iter = container.find(key);
    return iter!=container.end();
}

注意:这不是我正在使用的实际功能,而只是一些愚蠢的东西来证明这个问题.



1> David Rodríg..:

typename是标准所必需的.模板编译需要两步验证.在第一次传递期间,编译器必须验证模板语法,而不实际提供类型替换.在此步骤中,假定std :: map :: iterator是一个值.如果它确实表示类型,则typename关键字是必需的.

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

您可以使用以下代码进行检查:

class X {};
template 
struct Test
{
   typedef T value;
};
template <>
struct Test
{
   static int value;
};
int Test::value = 0;
template 
void f( T const & )
{
   Test::value; // during first pass, Test::value is interpreted as a value
}
int main()
{
  f( 5 );  // compilation error
  X x; f( x ); // compiles fine f: Test::value is an integer
}

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


失败案例的好例子
我认为你把你对两个调用的注释混淆了`f`,`f(X());`成功而``f(5);`是编译错误.无论如何,MSVC处理这个问题 - 它似乎延迟了`Test :: value`是否为值或类型的决定,直到模板被实例化为止.但是,对于类模板的成员,它不会这样做.

2> Magnus Hoff..:

好了,GCC实际上并不需要typedef- typename就足够了.这有效:

#include 
#include 

template
bool find(const std::map& container, const KEY& key)
{
    typename std::map::const_iterator iter = container.find(key);
    return iter!=container.end();
}

int main() {
    std::map m;
    m[5] = 10;
    std::cout << find(m, 5) << std::endl;
    std::cout << find(m, 6) << std::endl;
    return 0;
}

这是上下文敏感的解析问题的示例.有问题的行只是在这个函数的语法中不明显 - 你需要知道是否std::map::const_iterator是一个类型.

现在,我似乎无法想到一个例子,::const_iterator除了一个类型之外可能是什么...... 这也不是一个错误.所以我想编译器可以发现它必须是一个类型,但对于糟糕的编译器(编写器)来说可能很难.

根据标准typename第14.6/3节的要求,该标准要求使用此处.


编译器无法在没有typename的情况下解析的片段的简单示例:(X :: t)(y),是一个演员或函数调用?注意优先级也不同!无论谁将typedef添加到C都应该被拍摄:)
推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有