2016-11-22 60 views
1

比方說,我有一個這樣的結構:C++ 11的設定範圍根據使用結構爲元素

struct Something{ 
    string name; 
    int code; 
}; 

而且一套東西類型:

set<Something> myset; 
myset.insert({"aaa",123,}); 
myset.insert({"bbb",321}); 
myset.insert({"ccc",213}); 

這有什麼錯呢?

for (auto sth : myset){ 
     cout << sth.name; 
     cout << sth.code; 
} 

按照同樣的思路......我爲什麼不能修改元素使用這樣的事情(即使該集合包含普通int項目)?

for (auto &sth : myset){ 
     sth=[some value]; 
} 

我知道我可以用矢量和地圖做到這一點。爲什麼不設置?

謝謝!

回答

1

修改集合中的一個元素意味着它在集合順序中的位置可以改變。因爲您的編譯器無法知道特定集合用於確定其元素的訂單的具體內容。好吧,理論上它可以,但即使如此,在遍歷容器的同時跟蹤重新排列幾乎是不可能的。這是沒有意義的。

你可以做什麼,如果你想以一種你知道不會改變它們在一個集合中的順序的方式來修改集合中的元素,你可以讓你的結構的非排序成員是可變的。請注意,如果您犯了一個錯誤並且集合的順序受到干擾,那麼該集合上的任何其他操作(如二進制搜索)將在錯誤修改後給出錯誤結果。如果你不想讓成員變爲可變的,const_cast是一個選項,同樣需要注意。


要闡述我的回答上面,一個例子:

#include <iostream> 
#include <set> 

struct bla 
{ 
    std::string name; 
    int index; 
}; 

bool operator<(const bla& left, const bla& right) { return left.index < right.index; } 

int main() 
{ 
    std::set<bla> example{{"har", 1}, {"diehar", 2}}; 

    // perfectly fine 
    for(auto b : example) 
    std::cout << b.index << ' ' << b.name << '\n'; 

    // perfectly fine - name doesn't influence set order 
    for(auto& b : example) // decltype(b) == const bla& 
    const_cast<std::string&>(b.name) = "something"; 

    // better than first loop: no temporary copies 
    for(const auto& b : example) 
    std::cout << b.index << ' ' << b.name << '\n'; 

    // using a "universal reference auto&&", mostly useful in template contexts 
    for(auto&& b : example) // decltype(b) == const bla& 
    std::cout << b.index << ' ' << b.name << '\n'; 

    // destroying order of the set here: 
    for(auto& b : example) 
    const_cast<int&>(b.index) = -b.index; 

    // anything here relying on an ordered collection will fail 
    // This includes std::set::find, all the algorithms that depend on uniqueness and/or ordering 

    // This is pretty much all that will still work, although it may not even be guaranteed 
    for(auto&& b : example) 
    std::cout << b.index << ' ' << b.name << '\n'; 
} 

Live code on Coliru

請注意,第一個const_cast是正常的,因爲底層example不是const首先。

+0

謝謝!我現在明白了。第一部分呢?我沒有修改元素,只是試圖讀取它們,只是它們是結構的成員。爲什麼不允許? –

+0

您應該可以使用常量自動&通用適用的自動&&來做到這一點。雖然採取複製也應該工作太讓我檢查... – rubenvb

+0

看到更新與示例。 – rubenvb