2010-06-04 72 views
5

今天我的一个朋友告诉我,下面的代码编译以及他的Visual Studio 2008:Visual C++编译器允许从属名称作为没有“typename”的类型?

#include <vector> 
struct A 
{ 
    static int const const_iterator = 100; 
}; 
int i; 
template <typename T> 
void PrintAll(const T & obj) 
{ 
    T::const_iterator *i; 
} 
int main() 
{ 
    std::vector<int> v; 
    A a; 
    PrintAll(a); 
    PrintAll(v); 
    return 0; 
} 

我通常使用G ++,它总是拒绝通过第二PrintAll()调用。据我所知,对于这个问题,g ++正在做翻译模板的标准方式。

那么,我的知识是错误的,还是VS2008的扩展?

+0

这是/ Za(严格)还是/ Ze(默认,扩展)? – MSalters 2010-06-04 15:23:22

+0

@ MSalters:我刚刚尝试过/ ZA。没有看到任何区别... – hpsMouse 2010-06-04 15:56:04

回答

8

这不是一个扩展。

VC++从未付诸实施两个阶段的解释正确:

  1. 在定义的点,解析模板,并确定所有非依赖的名字
  2. 在实例化点,检查模板生成有效的代码

VC++从来没有实现第一阶段......这很不方便,因为它不仅意味着它接受不符合规范的代码,而且它在某些情况下会产生完全不同的代码。

void foo(int) { std::cout << "int" << std::endl; } 

template <class T> void tfoo() { foo(2.0); } 

void foo(double) { std::cout << "double" << std::endl; } 

int main(int argc, char* argv[]) 
{ 
    tfoo<Dummy>(); 
} 

有了这个代码:

  • 标准的编译器将打印“INT”,因为它是可在模板的定义和foo分辨率点的唯一定义不依赖于T
  • VC++将打印“双”,因为它从来没有与第1阶段

这似乎愚蠢尽可能的差异去打扰,但如果你仔细想想的数量包括你在一个大的程序,有是一种风险,有人会在你的模板代码之后引入过载...... BAM:/

+0

有没有办法让'VC++'至少产生一个警告?这种行为对于必须适用于多个编译器的代码来说是令人讨厌的。我们团队的开发人员忘记随时添加关键字,代码无法在'Clang'上编译# – Samaursa 2015-02-04 23:37:12

+1

@Samaursa:不幸的是,我不知道。如果你使用的是Clang,你可能会很感兴趣知道他们正在开发VC++的嵌入式驱动程序,因此你可以直接从Visual Studio调用Clang。 – 2015-02-05 07:22:36

1

我不确定“扩展”究竟是如何描述VC++在这方面的,但是,gcc在这方面有更好的一致性。

+0

这不是Visual Studio在宽容模式下的行为吗?我认为它会在严格模式下拒绝代码,并实现此扩展以便与VC6向后兼容。 – MSalters 2010-06-04 15:21:51

+0

@ MSalter:不,VC++即使使用/ Za也会接受该代码。 – 2010-06-04 15:43:43

相关问题