5

今天我的一个朋友告诉我,下面的代码在他的 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的扩展?

4

2 回答 2

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++ 将打印“double”,因为它从不打扰第 1 阶段

就差异而言,这可能看起来很愚蠢,但是如果您考虑在大型程序中包含的数量,则存在有人会在您的模板代码之后引入过载的风险......和 ​​BAM :/

于 2010-06-04T16:28:55.697 回答
1

我不确定“扩展”是否正是我在这方面描述 VC++ 的方式,但是是的,gcc 在这方面具有更好的一致性。

于 2010-06-04T14:18:47.520 回答