2014-03-07 24 views
3

我認爲擴大一個parameter pack有以下行爲:標準中定義了可變參數模板包擴展的順序嗎?

// for Args ... p 
f(p)...; 
// was equivalent to 
f(p1); f(p2); ...; f(pn); 

但我剛剛發現,海灣合作委員會(4.6,4.7和4.8)則正好相反:

f(pn); ...; f(p2); f(p1); 

而鐺如我所料。

這是GCC中的錯誤還是它們都是按照標準有效?

小例子

#include <iostream> 
#include <string> 

template<typename T> 
bool print(const unsigned index, const T& value){ 
    std::cerr << "Parameter " << index << " is " << value << std::endl; 
    return true; 
} 

template<typename ... Args> 
void printAll(Args ... args){ 
    unsigned i = 0; 
    [](...){}(print(i++, args)...); 
} 

int main(){ 
    int a = 1; float b = 3.14; std::string c("hello"); 
    printAll(a, b, c); 
} 

編譯和執行:

$> clang++ -std=c++11 -o test test.cpp 
$> ./test 
Parameter 0 is 1 
Parameter 1 is 3.14 
Parameter 2 is hello 
$> g++ -std=c++11 -o test test.cpp 
$> ./test 
Parameter 0 is hello 
Parameter 1 is 3.14 
Parameter 2 is 1 

回答

它沒有多久就Martinho費爾南des在這裏發現錯誤。的問題是參數計算的順序,這是不被標準(1.9.3)所定義的:

某些其它方面和抽象機的操作在本國際標準如 未指定的(例如描述,對函數的參數評估順序)。

+2

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56774 – galop1n

+1

這是一個已知的gcc錯誤。 Gcc 4.8.x修復了這個問題,但是引入了一個新的問題!請參閱bugzilla中的#59716。這個錯誤不會在不久的將來得到修復!沒有人在一個月內閱讀過此條目:-) – Klaus

+1

不,這不是GCC中的錯誤。有一個錯誤也導致了不想要的結果,但誰在乎?這並不是導致這種行爲的原因,因爲錯誤鏈接在4.6行中不存在。測試是打破,期間。 –

回答

12

是否在標準中定義了可變參數模板包擴展的順序?

是的。展開的元素的排列順序與包的原始順序相對應。

在測試中,擴展[](...){}(print(i++, args)...);相當於:[](...){}(print(i++, a), print(i++, b), print(i++, c));

該測試存在缺陷,因爲它測試函數參數的評估順序,這是一個完全不同的問題。如果您嘗試並執行上面展示的擴展表單,則會觀察到相同的行爲。或者如果代碼沒有未定義的行爲,你會這樣做,因爲變量i增加了幾次而沒有對增量進行排序。

+0

看起來很好,謝謝 – Thibaut

相關問題