2012-04-06 10 views
2

Was ich versuche, ist die Rückgabe eines ForwardIterator (oder sogar eines Paares von Begin- und End-Iteratoren), sodass die Uderlying-Implementierung von einer Clientklasse verborgen bleiben kann. Ich konnte kein solches Beispiel finden.Ausblenden der STL-Container-Implementierung durch Zurückgeben eines Iterators

Wenn die zugrunde liegende Implementierung Vektor ist, ist der Iterator vector :: iterator. Selbst wenn Sie die Ausgabe templatisieren, scheint dies nicht zu funktionieren.

+1

Was meinst du mit "scheint nicht zu funktionieren"? Bitte sei präziser. – larsmoa

+0

Können Sie Code anzeigen? Es ist schwer zu erraten, was in Ihrer Beschreibung falsch ist – plaisthos

Antwort

2

Sie können ein Objekt nicht gleichzeitig zurückgeben und erwarten, dass der Aufrufer seinen Typ nicht kennt. Die typische Art, den realen Typ eines Objekts zu "verstecken", besteht darin, es hinter einer Schnittstelle zu verstecken.

Zum Beispiel möchten Sie vielleicht so etwas schreiben:

template<typename T> 
class Cursor 
{ 
public: 
    typedef T value_type; 
    virtual ~Cursor() {} 
    virtual bool has_result() = 0; 
    virtual value_type get_result() = 0; 
}; 

// implements cursor interface for any sequence 
// described as a pair of forward iterators. 
template<typename I> 
class ForwardSequenceCursor : 
    public Cursor<std::iterator_traits<I>::value_type> 
{ 
    I myCurrent; 
    const I myEnd; 
public: 
    ForwardSequenceCursor(I begin, I end) 
     : myCurrent(current), myEnd(end) 
    {} 
    virtual bool has_result() { 
     return myCurrent != myEnd; 
    } 
    virtual value_type get_result() { 
     return *myCurrent++; 
    } 
}; 

Dann können Sie jede Vorwärtssequenz zurück, wie:

class Foo 
{ 
    std::vector<int> myValues; 
public: 
    std::unique_ptr< Cursor<int> > values() { 
     return std::unique_ptr< Cursor<int> >(
      new ForwardSequenceCursor<vector<int>::const_iterator>(
       myValues.begin(), myValues.end() 
      ) 
     ); 
    } 
}; 

Und wie nutzen so:

std::unique_ptr< Cursor<int> > cursor = foo.values(); 
while (cursor->has_result()) { 
    std::cout << cursor->get_result() << std::endl; 
} 
0

ForwardIterator ist ein Konzept, kein Typ. Sie müssen Ihre Funktion deklarieren, um einen Typ zurückzugeben.

0

Es gibt keine Basisklasse vom Typ „ForwardIterator“, ist die normale STL Art und Weise eine typedef zu einer tatsächlichen Iteratortyp hat in Ihrem Klasse, damit Client-Code es wie folgt verwenden kann:

MyClass :: iterator it = myclass.begin();

Nicht sehr gut als Verstecken geht, aber Sie können die Implementierung später ändern, ohne den Client-Code ändern zu müssen.

1

Sie können nicht direkt tun, was Sie versuchen zu tun, weil wie andere erwähnt haben, wenn Ihr Client goin ist Um einen Rückgabewert zu erhalten, muss er wissen, was dieser Rückgabewert ist.

Ein Weg, um es ist so etwas wie dies zu tun:

template<typename Collection> class MyClass 
{ 
    typedef Collection::iterator ReturnIt; 
    typedef std::pair<ReturnIt, ReturnIt> IteratorPair; 
    ReturnIt foo(); 
    IteratorPair bar(); 
}; 

Nun, dies entbindet uns nicht von Kunden des Containertyp zu sehen, aber die Schnittstelle ist nicht auf den Behältertyp gebunden.

Verwandte Themen