2016-04-24 6 views
3

Also, sagen Sie, ich habe eine Klasse, die std::list<std::pair<int, std::string>> darin hat; Wie kann ich einen Iterator für diese Klasse implementieren, so dass er über Strings in dieser Liste iteriert?Wie kann ich einen Iterator über Felder von Containern erstellen?

Oder zum Beispiel, in meiner Klasse Ich habe einen Vektor von struct s mit Feldern a, b und c; kann ich einen Iterator (vielleicht erben Vektor Iterator? weiß nicht), die, wenn dereferenziert, wird eine std::pair, die (b, c)?

von Iterator meine ich so etwas wie std::vector ‚s Iteratoren: etwas, das ich über whatever.begin() und iterieren bekommen kann, wie erwähnt, Strings in der Liste.

UPD Okay, hier ist mehr Informationen darüber, was ich will. In meiner HashMap Klasse habe ich items: eine Liste von structs: jeweils mit einem Schlüssel, einem Wert und einem Zeiger auf seinen Platz in der Tabelle. Was ich brauche, ist ein Iterator; aber nicht die, die ich bekommen kann, indem ich items.begin() mache, da dieser Iterator, wenn dereferenziert wird, meine Struktur zurückgibt. Ich brauche einen Iterator, so dass ich es zurückgeben kann, wenn der Benutzer HashMap.begin() aufruft, und es sollte in eine std::pair dereferenziert werden, die (Schlüssel, Wert) entspricht.

Dies sollte, hoffentlich, meine Frage klarer machen.

UPD2 Hier ist meine struct, wenn das hilft:

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

Sie können nicht für beliebige Strukturdefinitionen. Dies würde eine Laufzeit-Reflektion erfordern, die in C++ nicht verfügbar ist. Sie können Ihre eigene Iterator-Implementierung für jede konkrete Struktur bereitstellen, in der Sie diese jedoch verwenden müssen. Möglicherweise ist ['std :: tie()'] (http://en.cppreference.com/w/cpp/utility/tuple/tie) nützlich, wenn Sie dies tun. –

+0

Möchten Sie über die Strings in Ihrer Liste oder etwas anderes iterieren? – Galik

+0

Sie sollten erklären, warum Sie solche Iteratoren benötigen, weil es alternative Möglichkeiten gibt, dies zu tun. – Holt

Antwort

1

Eine elegante Weise Iteratoren oder einen transformierten Bereich zu verwenden, ist die Umwandlung:

#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'; 
} 

ein Iterator-Transformation zu verwenden für Sie Container können Sie etwas tun wie:

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

Nun, ich bin mir ziemlich sicher, dass ich 'Boost' und so nicht verwenden darf, also ... Während das großartig ist, hilft mir das nicht – Akiiino

+0

@Akiiino If Sie können den Boost nicht wiederverwenden, Sie können die zugrundeliegenden Ideen wiederverwenden: Erstellen Sie eine Iterator-Klassenvorlage für Ihren Container, ein Vorlagenparameter ist der Transformationsfunktions-/Extraktor-Objekttyp. –

Verwandte Themen