2011-04-06 103 views
6

考虑:C++语法歧义

void f(std::pair<bool,bool> terms = std::pair<bool,bool>(1,1)) {} 

GCC 4.4是好的,GCC 4.3抱怨error: expected ',' or '...' before '>' token。修复如下:

void f(std::pair<bool,bool> terms = (std::pair<bool,bool>(1,1))) {} 

是什么原因?这是4.3中的错误吗?

+0

这似乎是与最痛苦的解析(http://en.wikipedia.org/wiki/Most_vexing_parse)相关的东西。那么'std :: pair terms = std :: make_pair(true,true)'? – 2011-04-06 21:54:20

+1

为什么使用'1'作为布尔值?不要混合使用数字和布尔值,真的:/ – 2011-04-07 06:17:57

回答

8

这是一个已知的问题。它认为第二个逗号分隔参数声明。这是因为在类定义中,函数默认参数首先仅被标记化,然后才在完整的类体读取后才被解析。因为它并不真正解析默认参数,所以它并不会注意到逗号实际上是模板参数列表中的逗号。

请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#325的东西了解它。引用

另一个问题是收集构成默认参数表达式的标记。包含具有多个参数的template-id的默认参数在确定默认参数何时完成时存在困难。考虑一下,

template <int A, typename B> struct T { static int i;}; 
class C { 
    int Foo (int i = T<1, int>::i); 
}; 

默认参数包含一个非括号逗号。是否需要将此逗号看作默认参数表达式的一部分,而不是另一个参数声明的开始?要接受这个作为默认参数的一部分,需要在C完成之前对T进行名称查找(以确定'<'是模板参数列表的一部分,而不是小于运算符)。此外,病理性更强

class D { 
    int Foo (int i = T<1, int>::i); 
    template <int A, typename B> struct T {static int i;}; 
}; 

会很难接受。即使T是在Foo之后声明的,T在Foo默认参数表达式的范围内。

+4

C++很难:O – Anycorn 2011-04-06 21:57:31