C++;模板歧义 我和朋友正在讨论C++模板。他问我该怎么办: #include <iostream> template <bool> struct A { A(bool) { std::cout << "bool\n"; } A(void*) { std::cout << "void*\n"; } }; int main() { A<true> *d = 0; const int b = 2; const int c = 1; new A< b > (c) > (d); } #包括 模板 结构A{ A(bool){std::cout(d); }

C++;模板歧义 我和朋友正在讨论C++模板。他问我该怎么办: #include <iostream> template <bool> struct A { A(bool) { std::cout << "bool\n"; } A(void*) { std::cout << "void*\n"; } }; int main() { A<true> *d = 0; const int b = 2; const int c = 1; new A< b > (c) > (d); } #包括 模板 结构A{ A(bool){std::cout(d); },c++,templates,grammar,C++,Templates,Grammar,main中的最后一行有两个合理的解析。“b”是模板参数还是b>(c)是模板参数 尽管编译这个代码很简单,看看我们得到了什么,但我们想知道是什么解决了歧义?在没有括号的情况下,lexer的贪婪性可能是决定它显式的因素。我猜lexer不是贪婪的。如果它被编译成新的A(c)>d。这是IMHO解析它的唯一合理方法。如果解析器在正常情况下不能假定一个>结束模板参数,这将导致更多的歧义。如果您希望以另一种方式进行解析,您应该编写: new A<(b > c)>(d); 新的A c)>(d

main中的最后一行有两个合理的解析。“b”是模板参数还是
b>(c)
是模板参数


尽管编译这个代码很简单,看看我们得到了什么,但我们想知道是什么解决了歧义?

在没有括号的情况下,lexer的贪婪性可能是决定它显式的因素。我猜lexer不是贪婪的。

如果它被编译成
新的A(c)>d
。这是IMHO解析它的唯一合理方法。如果解析器在正常情况下不能假定一个>结束模板参数,这将导致更多的歧义。如果您希望以另一种方式进行解析,您应该编写:

new A<(b > c)>(d);
新的A c)>(d);

< P> C++ C++标准定义了如果对于一个模板名后面跟着一个<代码> <代码>操作符是模板参数,那么你需要把表达式括在括号中。如果这个参数是<代码> STATICEXCAST 或另一个模板表达式的一部分,则不需要括号。列昂和李,142/3(C++’03)所陈述的

< P>明确定义了这种行为

C++'0x通过应用于
>
的类似规则增加了乐趣。基本概念是,在解析模板参数列表时,非嵌套的
>
将被视为两个不同的
标记,而不是右移运算符:

template <bool>
struct A {
  A(bool);
  A(void*);
};

template <typename T>
class C
{
public:
  C (int);
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new C <A< b  >>  (c) > (d); // #1
    new C <A< b > >  (c) > (d); // #2
}
模板
结构A{
A(bool);
A(无效*);
};
模板
C类
{
公众:
C(国际);
};
int main(){
A*d=0;
常数int b=2;
常数int c=1;
新的C>(C)>(d);/#1
新的C>(C)>(d);/#2
}
#1和#2在上述情况下是等效的

这当然解决了在嵌套专门化中添加空格的麻烦:

C<A<false>> c;  // Parse error in C++ '98, '03 due to "right shift operator"
由于“右移运算符”C++ 98、03中的代码> C·//解析错误
但是词法分析不是完全明确的吗?它会在歧义上出错,所以是的。贪婪或不贪婪不会使你变得含糊不清。贪婪实际上是解决歧义的一种方法。在这种情况下,你也会进入词法分析程序和语法分析器之间的交互,所以可能是语法分析器不贪婪。语法可能是含糊不清的是的,但lexer绝对不是。空格使lexer完全定义得很好。我同意你的观点。我从来没有说过lexer是模糊的。我以前听说过这一点。一些编译器已经跳过了枪,允许
x
。但我只是想知道:它实际上是根据上下文敏感的lexing定义的,还是通过语法r定义的类似TemplateId“”的规则是单独给出的吗?@Stewart:这是前者(上下文敏感词法)。总之,14.2/3说,在解析模板参数列表时,第一个非嵌套的>>被视为两个单独的>标记。有关详细信息,您可以阅读实际文章: