2011-04-06 101 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