2016-04-24 59 views
3

所以,比如說,我有一個內部有std::list<std::pair<int, std::string>>的類;我怎麼能實現這個類的迭代器,以便它迭代這個列表中包含的字符串?如何在容器項目的字段上創建迭代器?

或者,例如,在我的班級中,我有一個向量struct s,其字段爲a,bc;我可以創建一個迭代器(也許是繼承向量的迭代器嗎?不知道),哪個在取消引用時會返回一個std::pair,對應於(b, c)

通過迭代器我的意思是像std::vector的迭代器的東西:我可以通過whatever.begin()得到的東西,並迭代,如上所述,列表中的字符串。

UPD好的,這裏有更多我想要的信息。在我的HashMap類中,我有itemsstructs的列表:每個都有一個鍵,一個值和一個指向它在表中的位置的指針。我需要的是一個迭代器;但不是我可以通過執行items.begin()得到的那個,因爲這個迭代器在解除引用時會返回我的結構。我需要一個迭代器,這樣我可以在用戶調用HashMap.begin()時返回它,並且它應該取消引用對應於(key,value)的std::pair

這應該希望能讓我的問題更清楚。

UPD2 這是我struct,如果這能幫助:

template<class KeyType, class ValueType> 
struct node { 
    KeyType key; 
    ValueType value; 
    node** place; 

    node(KeyType key_ = KeyType(), ValueType value_ = ValueType()): key(key_), value(value_) {}; 
}; 
+0

你不能爲任意的結構定義。這需要運行時反射,這在C++中是不可用的。您可以爲每個具體結構提供您自己的迭代器實現,儘管您需要使用它。可能['std :: tie()'](http://en.cppreference.com/w/cpp/utility/tuple/tie)在這樣做時很有用。 –

+0

你想迭代你的列表中的字符串還是其他的東西? – Galik

+0

你應該解釋**爲什麼**你需要這樣的迭代器,因爲可能有其他的方法。 – Holt

回答

1

一種優雅的方式是使用轉化迭代器或轉換範圍:

#include <iostream> 
#include <list> 
#include <boost/range/adaptor/transformed.hpp> 
#include <boost/iterator/transform_iterator.hpp> 

int main() { 
    std::list<std::pair<int, std::string>> l; 
    auto extractor = [](auto&& elem) { return elem.second; }; 

    // Using a transformed range. 
    for(auto&& v: l | boost::adaptors::transformed(extractor)) 
     std::cout << v << '\n'; 

    // Using transform iterators. 
    for(auto i = boost::make_transform_iterator(l.begin(), extractor), j = boost::make_transform_iterator(l.end(), extractor); i != j; ++i) 
     std::cout << *i << '\n'; 
} 

要使用一個轉換迭代器你的容器你可以這樣做:

struct MyContianer 
{ 
    std::list<std::pair<int, std::string>> container; 

    static auto constexpr first_extractor = [](auto&& elem) { return elem.second; }; 
    using iterator_first = decltype(boost::make_transform_iterator(container.begin(), first_extractor)); 
    iterator_first begin_first() { return {container.begin(), first_extractor}; } 
    iterator_first end_first() { return {container.end(), first_extractor}; } 

    static auto constexpr second_extractor = [](auto&& elem) { return elem.second; }; 
    using iterator_second = decltype(boost::make_transform_iterator(container.begin(), second_extractor)); 
    iterator_second begin_second() { return {container.begin(), second_extractor}; } 
    iterator_second end_second() { return {container.end(), second_extractor}; } 

}; 
decltype(MyContianer::first_extractor) constexpr MyContianer::first_extractor; 
decltype(MyContianer::second_extractor) constexpr MyContianer::second_extractor; 

int main() { 
    MyContianer c; 
    c.begin_first(); 
    c.begin_second(); 
} 
+0

嗯,我很確定我不被允許使用'boost'等等,所以...雖然這很棒,但這並不能幫助我 – Akiiino

+0

@Akiiino If你不能重用boost,你可以重用底層思想:爲你的容器創建一個迭代器類模板,一個模板參數是transform函數/提取器對象類型。 –