C++ 为什么非类型模板参数表达式在编译器之间处理不一致?

C++ 为什么非类型模板参数表达式在编译器之间处理不一致?,c++,compiler-construction,templates,C++,Compiler Construction,Templates,下面是我在各种编译器中观察到的情况。似乎有编译器错误 template <int I> struct X { }; int main(void) { X<(16 > 1)> a; // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 X<(int(16) > 1)> b; // Works on vc9, works on g++ 4.1.2, works

下面是我在各种编译器中观察到的情况。似乎有编译器错误

template <int I>
struct X
{ };

int main(void)
{
  X<(16 > 1)> a;       // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1
  X<(int(16) > 1)> b;  // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1
  X<(16 >> 1)> c;      // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1
  X<(int(16) >> 1)> d; // Fails on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1

  X<16 > 1> e;         // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1
  X<int(16) > 1> f;    // Fails on vc9, fails on g++ 4.1.2, fails on Comeau 4.3.10.1
  X<16 >> 1> g;        // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1
  X<int(16) >> 1> h;   // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1
 }
模板
结构X
{ };
内部主(空)
{
x1)>a;//适用于vc9,适用于g++4.1.2,适用于Comeau 4.3.10.1
x1)>b;//适用于vc9,适用于g++4.1.2,适用于Comeau 4.3.10.1
十> 1)>c;//适用于vc9,适用于g++4.1.2,适用于Comeau 4.3.10.1
十> 1)>d;//在vc9上失败,在g++4.1.2上工作,在Comeau 4.3.10.1上工作
X 1>e;//在vc9上失败,在g++4.1.2上工作,在Comeau 4.3.10.1上失败
X 1>f;//在vc9上失败,在g++4.1.2上失败,在Comeau 4.3.10.1上失败
十> 1>g;//在vc9上失败,在g++4.1.2上工作,在Comeau 4.3.10.1上失败
十> 1>h;//在vc9上失败,在g++4.1.2上工作,在Comeau 4.3.10.1上失败
}
为什么不一致?标准允许/不允许什么?在vc9上使用BOOST_AUTO时,这种行为也会导致语法错误。在我看来,Comeau通过拒绝所有不带括号的表达式来做正确的工作。

根据:“第一个非嵌套>终止模板参数列表。如果需要大于,则必须使用括号。”


因此,容忍第二组表达式的编译器这样做是错误的;在
X>1)>d上失败的编译器有缺陷。

C++03的规则如下:

名称查找(3.4)后发现名称是模板名称,如果该名称后面跟一个
,该名称包含
动态\u cast
静态\u cast
重新解释\u cast
常量cast
,或包含后续模板id的模板参数,在本说明中被认为是嵌套的。]作为模板参数列表的结尾,而不是大于运算符

因此,结果是:

  X<(16 > 1)> a;       // works
  X<(int(16) > 1)> b;  // works
  X<(16 >> 1)> c;      // works
  X<(int(16) >> 1)> d; // works

  X<16 > 1> e;         // fails
  X<int(16) > 1> f;    // fails
  X<16 >> 1> g;        // works (">>" is not a ">" token)
  X<int(16) >> 1> h;   // works (">>" is not a ">" token). 

测试时一定要禁用comeau中的C++0x模式

我认为这与模板是非类型无关,而是因为它在模板中使用了“>”字符。你说得对,我在用户定义类的重载'>'和'>>'运算符中看到过这种不一致的行为。因为这是一种很少使用的构造,因此不太可能进行测试。不管怎样,在真实的代码中使用它们都会让你发疯。但是值得将这些作为测试提交给编译器制造商,这样他们就可以将其添加到他们的测试套件中,让人们做一些疯狂的事情。我想很难发现编译器只在一个主题上有这么大的不同:)很好。为了提高每个人的编译器质量,您应该提交一份GCC错误报告,并执行MSVC的任何等效过程。这意味着在X>1>上失败的编译器也有错误,因为>>不是两个>(著名的嵌套模板滋扰)回答得很好!在Comeau上,禁用C++0x时,结果如上所述(6项工作,2项失败)。您也可以随时依靠litb进行研究:)
  X<(16 > 1)> a;       // works
  X<(int(16) > 1)> b;  // works
  X<(16 >> 1)> c;      // works
  X<(int(16) >> 1)> d; // works

  X<16 > 1> e;         // fails
  X<int(16) > 1> f;    // fails
  X<16 >> 1> g;        // fails (">>" translated to "> >")
  X<int(16) >> 1> h;   // fails (">>" translated to "> >")