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

标签 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 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
 }

为什么会出现这种不一致?标准允许/不允许什么?在 vc9 上使用 BOOST_AUTO 时,这种行为也会导致语法错误。在我看来,Comeau 拒绝所有不带括号的表达式是正确的。

最佳答案

C++03规则如下:

After name lookup (3.4) finds that a name is a template-name, if this name is followed by a <, the < is always taken as the beginning of a template-argument-list and never as a name followed by the less-than operator. When parsing a template-id, the first non-nested > [foot-note: A > that encloses the type-id of a dynamic_cast, static_cast, reinterpret_cast or const_cast, or which encloses the template-arguments of a subsequent template-id, is considered nested for the purpose of this description. ] is taken as the end of the template-argument-list rather than a greater-than operator.

所以结果是:

  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). 

但是,在 C++0x 中有以下规则

After name lookup (3.4) finds that a name is a template-name, or that an operator-function-id refers to a set of overloaded functions any member of which is a function template, if this is followed by a <, the < is always taken as the delimiter of a template-argument-list and never as the less-than operator. When parsing a template-argument-list, the first non-nested > [foot-note: A > that encloses the type-id of a dynamic_cast, static_cast, reinterpret_cast or const_cast, or which encloses the template-arguments of a subsequent template-id, is considered nested for the purpose of this description.] is taken as the ending delimiter rather than a greater-than operator. Similarly, the first non-nested >> is treated as two consecutive but distinct > tokens, the first of which is taken as the end of the template-argument-list and completes the template-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;        // fails (">>" translated to "> >")
  X<int(16) >> 1> h;   // fails (">>" translated to "> >")

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

关于c++ - 为什么非类型模板参数表达式处理在编译器之间不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1595859/

相关文章:

c++ - 将 C++11 枚举类作为模板传递,同时自动推导其类型

c++ - 你能向我解释一下变形方法的这一部分吗(使用 OpenCV、C++ 和 Qt)?

c++ - gtest - 确保某个方法之前没有被调用,但可以在某个方法调用之后被调用

c++ - Visual Studio 2012 项目中的 tesseract Remove_Reference 模糊符号

c# - 自动属性上的 INotifyPropertyChanged-Feature

html - gmail 和 outlook 无法正确呈现电子邮件模板

c++ - 如何让 MyClass 的用户通过编译器标志控制类的哪个版本被实例化?

compiler-construction - 是否有适用于 x86 或 x86_64 的 lolcode 编译器?

gcc - g++ 或 gcc 选项来获取带有警告 ID 的警告消息

c++ - 如何使用 auto 和 decltype 关键字来简化模板参数推导?