Visual C ++编译器允许dependent-name作为没有“typename”的类型?

时间:2010-06-04 13:59:46

标签: c++ visual-c++ templates dependent-name

今天我的一位朋友告诉我,下面的代码在他的Visual Studio 2008上编译得很好:

#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的扩展?

2 个答案:

答案 0 :(得分:8)

这根本不是扩展名。

VC ++从未正确实现过两个阶段的解释:

  1. 在定义时,解析模板并确定所有非依赖名称
  2. 在实例化时,检查模板是否生成有效代码
  3. 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 ++将打印“double”,因为它从未打扰过阶段1

    就差异而言,这看起来似乎很愚蠢,但是如果你考虑一下大型程序中包含的数量,那么有人会在你的模板代码之后引入一个重载......和BAM:/

答案 1 :(得分:1)

我不确定“扩展”是我在这方面描述VC ++的原因,但是,gcc在这方面的表现更好。