类模板中名称解析的实际结果与c ++ 03标准不同 [英] The actual result of name resolution in the class template is different from the c++ 03 standard

查看:152
本文介绍了类模板中名称解析的实际结果与c ++ 03标准不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Xcode 4.1和Visual Studio 2008上测试c ++标准ISO / IEC 14882-03 14.6.1 / 9中的代码。两个编译器的输出都与标准的预期结果不同。



代码在下面粘贴。

  #include< stdio.h> 
#include< iostream>
using namespace std;

void f(char);

template< class T> void g(T t)
{
f(1);
f(T(1));
f(t);
}

void f(int);
void h()
{
g(2);
g('a');
}

void f(int)
{
cout< f int< endl;
}


void f(char)
{
cout< f char< endl;
}


int main(){
h();
return 0;
}

作为标准的描述。预期输出应为

  f char 
f int
f int
f char
f char
f char

在Xcode 4.1上构建并运行代码。输出如下所示。在构建设置中,我试图将Compiler for C / C ++ / Object-C更改为Apple LLVM Compiler 2.1,Gcc 4.2和LLVM GCC 4.2。输出是相同的。

  f char 
f char
f char
f char
f char
f char

在Microsoft Visual Studio 2008上构建并运行代码。输出如下。

  f int 
f int
f int
f int
f char
f char

标准的描述(14.6.1 / 9) / p>

如果名称不依赖于模板参数(如14.6.2中定义),那么该名称的声明(或一组声明)范围在名称出现在模板定义中的点;该名称将绑定到在该点找到的声明(或声明),并且此绑定不受在实例化时可见的声明的影响。 [示例:

  void f(char); 
template< class T> void g(T t)
{
f(1); // f(char)
f(T(1)); // dependent
f(t); // dependent
dd ++; // not dependent
}
void f(int);
double dd;
void h()
{
//错误:未找到dd的声明
g(2); //将调用f(char)调用//调用两次f(int)
g('a'); //将引起三次调用f(char)


$ b

代码与编译器格式良好,但输出是不同的。将此代码移植到不同的平台是非常危险的。



有人有背景为什么这些编译器不遵循标准?



于2011年11月11日编辑



Per http://www.open-std.org/jtc1/sc22/wg21/ docs / cwg_defects.html#197 ,标准中的示例是错误的。我在Clang和Gcc上测试下面的代码。

  #include< stdio.h> 
#include< iostream>
using namespace std;

void f(char);

template< class T> void g(T t)
{
f(1);
f(T(1));
f(t);
}

枚举E {e};

void f(E);
void h()
{
g(e);
g('a');
}

void f(E)
{
cout< f E<< endl;
}

void f(char)
{
cout< f char< endl;
}

int main(){
h();
return 0;
}

输出符合预期。


$ b b

  f char 
f E
f E
f char
f char
f char



感谢,



Jeffrey

解决方案

如第一个示例所示,这是一个两阶段名称查找的实例,GCC和Clang都实现,但MSVC不实现。在这种情况下,GCC和Clang都是正确的:它实际上是错误的标准,如C ++中所述 core defect report#197 。 C ++ 11标准包含一个不同的示例。



这是我们看到当从MSVC(从未实现两阶段名称查找)或从GCC(其没有实现两阶段名称查询)移植代码到Clang的最常见的问题直到最近)。


I test the code in the c++ standard ISO/IEC 14882-03 14.6.1/9 on Xcode 4.1 and Visual Studio 2008. The outputs of the two compiler are both different from the expected result of the standard.

The code is pasted below.

#include <stdio.h>
#include <iostream>
using namespace std;

void f(char);

template <class T > void g(T t)
{
    f(1);
    f(T(1));
    f(t);
}

void f(int);
void h()
{
    g(2);
    g('a');
}

void f(int)
{
     cout << "f int" << endl;
}


void f(char)
{
    cout << "f char" << endl;
}


int main() { 
    h();  
    return 0;
}

As the description of the standard. The expected output should be

f char
f int
f int
f char
f char
f char

Build and run the code on Xcode 4.1. The output is as below. In the build settings, I tried to change the "Compiler for C/C++/Object-C" to be Apple LLVM Compiler 2.1, Gcc 4.2 and LLVM GCC 4.2. The outputs are the same.

f char
f char
f char
f char
f char
f char

Build and run the code on Microsoft Visual Studio 2008. The output is as below.

f int
f int
f int
f int
f char
f char

The description (14.6.1/9) of the standard is pasted below.

If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declara- tions) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation. [Example:

void f(char);
template<class T> void g(T t)
{
f(1); // f(char) 
f(T(1)); // dependent 
f(t); // dependent 
dd++; // not dependent
}
void f(int);
double dd;
void h()
{
// error: declaration for dd not found
g(2); // will cause one call of f(char) followed // by two calls of f(int)
g(’a’); // will cause three calls of f(char) 

—end example]

The code is well-formed to the compilers, but the outputs are different. It would be very dangerous to port this code to different platforms.

Does somebody have the background why these compilers don't follow the standard?

Edit on 10/11/2011

Per http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#197, the example in the standard is wrong. I test the code below on Clang and Gcc.

#include <stdio.h>
#include <iostream>
using namespace std;

void f(char);

template <class T > void g(T t)
{
    f(1);
    f(T(1));
    f(t);
}

enum E{ e };

void f(E );
void h()
{
    g(e);
    g('a');
}

void f(E )
{
    cout << "f E" << endl;
}

void f(char)
{
    cout << "f char" << endl;
}

int main() { 
    h();  
    return 0;
}

The output as expected.

f char
f E
f E
f char
f char
f char

Thanks,

Jeffrey

解决方案

As noted in the first example, this is an instance of two-phase name lookup, which both GCC and Clang implement but MSVC does not. And in this case, both GCC and Clang are correct: it's actually the standard that is wrong, as noted in C++ core defect report #197. The C++11 standard contains a different example.

This is one of the most common problems we see when porting code to Clang from either MSVC (which never implemented two-phase name lookup) or from GCC (which didn't implement two-phase name lookup uniformly until recently).

这篇关于类模板中名称解析的实际结果与c ++ 03标准不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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