简体   繁体   English

C ++模板歧义

[英]C++ Template Ambiguity

A friend and I were discussing C++ templates. 我和朋友正在讨论C ++模板。 He asked me what this should do: 他问我应该做什么:

#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);
}

The last line in main has two reasonable parses. main中的最后一行有两个合理的解析。 Is 'b' the template argument or is b > (c) the template argument? 'b'是模板参数还是b > (c)模板参数?

Although, it is trivial to compile this, and see what we get, we were wondering what resolves the ambiguity? 虽然编译这个很简单,看看我们得到了什么,但我们想知道是什么解决了歧义?

As stated by Leon & Lee, 14.2/3 (C++ '03) explicitly defines this behaviour. 正如Leon&Lee所述,14.2 / 3(C ++ '03)明确定义了这种行为。

C++ '0x adds to the fun with a similar rule applying to >> . C ++'0x通过适用于>>的类似规则增加了乐趣。 The basic concept, is that when parsing a template-argument-list a non nested >> will be treated as two distinct > > tokens and not the right shift operator: 的基本概念,是解析模板参数列表的非嵌套时>>将作为两个不同待处理> >令牌而不是向右移位运算符:

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
}

'#1' and '#2' are equivalent in the above. “#1”和“#2”在上面等同。

This of course fixes that annoyance with having to add spaces in nested specializations: 这当然解决了必须在嵌套特化中添加空格的烦恼:

C<A<false>> c;  // Parse error in C++ '98, '03 due to "right shift operator"

AFAIK it would be compiled as new A<b>(c) > d . AFAIK它将被编译为new A<b>(c) > d This is the only reasonable way to parse it IMHO. 这是解析它的唯一合理方法恕我直言。 If the parser can't assume under normal circumstances a > end a template argument, that would result it much more ambiguity. 如果解析器在正常情况下无法假设>结束模板参数,那将导致更加模糊。 If you want it the other way, you should have written: 如果你想要另一种方式,你应该写:

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

The C++ standard defines that if for a template name followed by a < , the < is always the beginning of the template argument list and the first non-nested > is taken as the end of the template argument list. C ++标准定义如果对于模板名称后跟一个< ,则<始终是模板参数列表的开头,而第一个非嵌套的>被视为模板参数列表的末尾。

If you intended that the result of the > operator be the template argument, then you'd need to enclose the expression in parentheses. 如果您打算将>运算符的结果作为模板参数,那么您需要将表达式括在括号中。 You don't need parentheses if the argument was part of a static_cast<> or another template expression. 如果参数是static_cast<>或其他模板表达式的一部分,则不需要括号。

The greediness of the lexer is probably the determining factor in the absence of parentheses to make it explicit. 词法分析器的贪婪可能是没有括号使其明确的决定因素。 I'd guess that the lexer isn't greedy. 我猜这个词法分析器并不贪心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM