2017-11-29 2 views
0

Ich habe eine Sammlung von Objekt des Typs "T", die ich durchlaufen möchte. Ein Objekt vom Typ „T“ hat zwei wichtige Eigenschaften:Benutzerdefinierte Iterator-Funktion für C++

int r; // row number 
int c; // column number 

Ich möchte einen Iterator definieren, die mich durch alle Elemente der Kollektion iterieren ermöglicht.

Dies kann mit Hilfe getan werden:

std::vector<T> v; 

for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) { 
    .... 
} 

Allerdings habe ich den Iterator möchte eine weitere Eigenschaft haben. Ich möchte in der Lage sein

it.nextrow() 

Aufruf dieser Funktion aufrufen, sollte das Element „e“ von v zurück, wo er + 1 = ec.r und ec = ec.c, wo ec das aktuelle Element ist darauf durch der Iterator. I.e. Das Aufrufen von it.nextrow() sollte mir einen Zeiger auf das Element geben, wo die Spalte gleich ist, aber die Zeile um eins erhöht wird. Ich hoffe es macht Sinn.

Ich bin nicht sicher, was ich tun muss, damit dies funktioniert, da ich ziemlich neu in fortgeschrittenen C++ - Konzepten bin. Kann mir jemand helfen?

+0

Können Sie genauer erklären, wie Ihre Daten strukturiert sind? Ich sehe nicht die Beziehung zwischen 'std :: vector ' und 'int r, c'.Verfügen Sie über einen Vektor von Zeilenobjekten, in denen jede Zeile eine Auflistung von Spaltenwerten enthält, oder haben Sie ein flaches Layout, in dem alle Spalten einer Zeile im Vektor aufeinander folgen? – grek40

Antwort

2

Nicht alles muss eine Mitgliedsfunktion sein. Würden Sie eine iterator nextRow(iterator current, iterator begin, iterator end) freie Funktion akzeptieren?

Wenn Ihr Vektor immer sortiert ist, brauchen Sie keinen separaten Anfang, verwenden Sie einfach die Nadel.

Wenn Sie dies als Teil eines Wrapper-Iterators benötigen, muss dieser Typ ein Anfang und ein Ende enthalten.

template <typename Iterator> 
class SearchableIterator 
{ 
    Iterator wrapped, begin, end; 
public: 
    difference_type  Iterator::difference_type; 
    value_type   Iterator::value_type; 
    pointer    Iterator::pointer; 
    reference   Iterator::reference 
    iterator_category Iterator::iterator_category 

    SearchableIterator(Iterator wrapped, Iterator begin, Iterator end) 
     : wrapped(wrapped), begin(begin), end(end) {} 

    // All the members, calling that member of wrapped (see std::reverse_iterator for guidance) 

    SearchableIterator nextRow() 
    { 
     return SearchableIterator(std::find_if(begin, end, [this](const T & elem) { return (elem.r == wrapped->r + 1) && (elem.c == wrapped->c); }), begin, end); 
    } 
} 
+0

Ich implementiere einen Teil eines Codes, wo meine Schnittstellen behoben sind. Daher muss ich in der Lage sein, es in der Form it.nextrow() zu verwenden. Ist das möglich? –

+0

Ja, jedoch können Sie keine Mitglieder zu 'std :: vector :: iterator' hinzufügen. Sie müssen einen Wrapper schreiben. Es benötigt dieselben Daten wie die nextRow-Funktion. – Caleth

0

Iteratoren sind kopierbar.

Sie können

  • vom Iterators Behälter für Behälter ableiten,
  • hinzufügen Bau aus dem Behälter des Iterators,
  • hinzufügen Ihre persönliche Eigenschaft Mitglieder,
  • und erklärt, dass begin(), end() usw. aus Ihrem benutzerdefinierten Container geben den abgeleiteten Iterator zurück.
0

Ihre Daten Angenommen, in einem Vektor mit aufeinander folgenden Elementen für alle Spalten einer Reihe von Positionen der nächsten Zeile gefolgt gepackt sind, würden Sie nur *(iterator + column_count) brauchen den nächste Zeile-same-Spalt Wert (don‘zugreifen t versuchen, dies auf einem Iterator, der bereits in der letzten Reihe der Daten zeigt)

Sie einen Wrapper Iterator ähnlich wie Implement custom iterator for c++ std container erstellen und geben ihm eine bestimmte Spalte zählen als Zusatzinformation:

template<typename T, int colsize, typename TIterator = std::vector<T>::iterator> 
class MyRowIterator : public std::iterator<std::forward_iterator_tag, T> 
{ 
private: 
    TIterator m_pter; 
public: 

    MyRowIterator(TIterator& value): m_pter(value) 
    { 
    } 
    MyRowIterator(const MyRowIterator& other_it): m_pter(other_it.m_pter) 
    { 
    } 
    MyRowIterator& operator++() 
    { 
     ++m_pter; 
     return *this; 
    } 
    bool operator!=(const MyRowIterator& rhs) 
    { 
     return m_pter != rhs.m_pter; 
    } 
    T& operator*() 
    { 
     return (*m_pter); 
    } 
    // here it is 
    T& nextrow() 
    { 
     return *(m_pter+colsize); 
    } 
}; 

Anwendungsbeispiel:

void Test() 
{ 
    std::vector<int> data; 

    // 2 rows each 10 columns 
    data.resize(20); 
    for (auto& item : data) 
    { 
     item = 0; 
    } 
    data[2] = 1; 
    data[12] = 5; 

    // don't iterate the last line, else nextrow() will access out of bounds! 
    for (MyRowIterator<int, 10> iter = data.begin(); iter != (data.end()-10); iter++) 
    { 
     std::cout << *iter << " # " << iter.nextrow() << std::endl; 
    } 
} 
Verwandte Themen