2014-01-23 41 views
16

我想要做的東西像下面這樣:使用std ::領帶的範圍內環路目標

//std::vector<std::pair<TypeA, TypeB>> someInitializingFunction(); 
{ 
    TypeA a; 
    TypeB b; 

    for (std::tie(a, b) : someInitializingFunction()) { 
    // do stuff; 
    } 
} 

然而,這不是有效的代碼,因爲,作爲標準說,基於for循環的範圍是定義爲等同於:

{ 
    auto && __range = range-init; 
    for (auto __begin = begin-expr, 
     __end = end-expr; 
     __begin != __end; 
     ++__begin) { 
    for-range-declaration = *__begin; 
    statement 
    } 
} 

凡爲範圍聲明定義爲:

換範圍聲明: ATTR ibute-specifier-seq_ {opt} decl-specifier-seq聲明者

那麼,讓我回想起decl-specifier-seq沒有標記爲可選的?

因此,看來我必須求助於傳統風格的for循環爲這一個一拉:

std::vector<std::pair<TypeA, TypeB>> myList = someInitializingFunction(); 

{ 
    TypeA a; 
    TypeB b; 

    for (auto it = myList.begin(); it != myList.end(); ++it) { 
    std::tie(a, b) = *it; 
    // do stuff; 
    } 
} 

但它似乎有點語法什麼似乎直覺是一個相當常見的任務凌亂,拆包函數調用的結果,在許多其他情況下都是有效的。

有沒有建議在語言中增加一些東西?這是否合理?有沒有更好的方法來做到這一點,我忽略了?我誤讀了標準嗎?

顯然,我可以把自己的功能放在一起來做到這一點,但這也有點混亂。

+2

**更新:**它也許可以做,在C++ 17具有非常直觀的語法。 [他們目前在「結構化綁定」工作](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0144r0.pdf)。然後可以這樣做:for(auto {a,b}:myList)'。 – leemes

回答

13

您仍然可以使用範圍!

//std::vector<std::pair<TypeA, TypeB>> someInitializingFunction(); 
{ 
    TypeA a; 
    TypeB b; 

    for (auto& p : someInitializingFunction()) { 
    std::tie(a, b) = p; 
    // do stuff; 
    } 
} 

或者const auto& p如果你並不需要/想修改p

UPDATE:通過上述,您還可以使用std::move

for (auto& p : someInitializingFunction()) { 
    std::tie(a, b) = std::move(p); 
    // do stuff; 
} 

移動元素的綁定變量爲這你提出的語法可能無法處理好。一個人爲的例子:

for (std::tie(a, b) : std::move(someInitializingFunction())) {} 
// Note: std::move here is superfluous, as it's already an r-value 
// (may also hinder some optimizations). Purely for demonstration purposes. 

就這樣,不必移動元件與綁變量的值的能力,如begin()end()等從r值容器不會產生移動迭代器。 (嗯,是的,你可以將容器調整爲返回迭代器的東西,但這將是一個全新的故事)

+0

好吧,我現在感到很蠢! – OmnipotentEntity

+5

如果'TypeA'和'TypeB'不是default-constructible? – knedlsepp

3

截至2017年3月21日,結構化綁定是C++的一部分。

這允許直接執行以下操作:

//std::vector<std::pair<TypeA, TypeB>> someInitializingFunction(); 
for (auto [a, b] : someInitializingFunction()) { 
    // do stuff; 
} 
+0

「*是C++ *的一部分」,C++標準並不持續發展。它的版本發佈。所以,我猜這個日期是註定要成爲下一個C++標準的一部分 - 我猜是C++ 17。我正在挑剔這個,因爲可悲的是我不會得到後向支持從C++ 11。無論如何+1保持答案/問題最新。 – luk32