2012-12-27 35 views
19

other topic,@Dietmar了此解決方案:順序列表初始化元素的評價

template <typename... T> 
std::tuple<T...> parse(std::istream& in) 
{ 
    return std::tuple<T...>{ T(in)... }; 
} 

指出,

使用支具初始化的工作,因爲秩序評價參數在大括號初始化列表是它們出現的次序。 (強調雷)

從C++標準(n3485)中的有關內容,

在一個支撐,初始化列表的初始化列表,初始化-條款,包括任何導致從包裝展開(14.5.3)開始,按其出現的順序進行評估。也就是說,與給定初始化子句相關聯的每個值計算和副作用在與初始值設定項列表的逗號分隔列表中的任何初始化子句相關聯的每個值計算和副作用之前排序。 [注意:不管初始化的語義如何,這個評估順序都成立;例如,當初始化器列表的元素被解釋爲構造函數調用的參數時,即使通常對調用的參數沒有排序約束,也適用。末端注]


所以我試着用下面的代碼來測試這個:

template<int N> 
struct A 
{ 
    std::string data; 
    A(std::istream & stream) { stream >> data; } 
    friend std::ostream& operator<<(std::ostream & out, A<N> const & a) 
    { 
     return out << "A"<<N<<"::data = " << a.data; 
    } 
}; 
typedef A<1> A1; 
typedef A<2> A2; 

template<typename ...Args> 
void test(std::istream & stream) 
{ 
    std::tuple<Args...> args { Args(stream)... }; 
    std::cout << std::get<0>(args) << std::endl; 
    std::cout << std::get<1>(args) << std::endl; 
} 

int main() 
{ 
    std::stringstream ss("A1 A2"); 
    test<A1,A2>(ss); 
} 

預期輸出:

A1::data = A1 
A2::data = A2 

實際輸出:

A1::data = A2 
A2::data = A1 

我在測試代碼中做了什麼錯誤嗎?我將我的代碼更改爲:

std::stringstream ss("A1 A2"); 
std::tuple<A1,A2> args{A1(ss), A2(ss)}; 
std::cout << std::get<0>(args) << std::endl; 
std::cout << std::get<1>(args) << std::endl 

與以前相同的輸出。我用MinGW (GCC) 4.7.04.7.2測試了我的代碼。即使ideone給出this output

它是編譯器中的錯誤嗎?

+0

clang-3.2生成預期的輸出。也許這是海灣合作委員會的錯誤? –

+4

這是一個GCC錯誤。鏗鏘得到它正確。 – Xeo

+4

你對我們的期望是什麼? 「是的,這是一個錯誤,因爲你給的報價」。這不是今天說過兩次嗎?在@Dietmar和Dietmar提到的問題中,都給出了引用和例子,說明順序是從左到右的。 –

回答

8

回答我自己的問題。刪除問題不是一個好主意,因爲將來有人可能會有同樣的問題。

是的。這是GCC編譯器中的一個錯誤。

從@Johannes紹布對問題的意見作出。

+2

需要注意的是微軟的Visual Studio 12(2013)具有相同的錯誤,我只是在https://connect.microsoft.com/報道VisualStudio/feedbackdetail/view/976911/braced-initializer-list-not-evaluate-left-to-right – Oberon

+0

是否有解決MSVC的問題? – Ram

+0

這將被固定在MSVC 2015更新2(https://blogs.msdn.microsoft.com/vcblog/2016/02/11/compiler-improvements-in-vs-2015-update-2/) –