Frage

Ich habe jetzt eine Zeit lang C # unter Verwendung von und zu C ++ zurück ist ein Kopfschmerz. Ich versuche, einige meine Praktiken von C # mit mir zu C ++ zu bekommen, aber ich bin etwas Widerstand zu finden, und ich würde mich freuen, Ihre Hilfe zu akzeptieren.

Ich möchte einen Iterator für eine Klasse wie folgt aussetzen:

template <class T>
class MyContainer
{
public:
    // Here is the problem:
    // typedef for MyIterator without exposing std::vector publicly?

    MyIterator Begin() { return mHiddenContainerImpl.begin(); }
    MyIterator End() { return mHiddenContainerImpl.end(); }

private:
    std::vector<T> mHiddenContainerImpl;
};

Bin ich auf etwas versuchen, das ist kein Problem? Sollte ich nur typedef std :: vector :: iterator? Ich hoffe auf nur abhängig von dem Iterator, nicht die Umsetzung der Container ...

War es hilfreich?

Lösung

Sie können unter den folgenden Artikel interessant finden, da es genau das Problem Adressen, die Sie gebucht haben: Auf der Tension zwischen Objektorientierte und generischer Programmierung in C ++ und welcher Art Erasure über es tun

Andere Tipps

ich habe folgende vor getan, damit ich einen Iterator bekam, die unabhängig von dem Behälter war. Das mag übertrieben gewesen, da ich auch eine API verwendet haben könnte, wo der Anrufer in einem vector<T*>& gibt, der mit allen Elementen bestückt werden soll, und dann kann der Anrufer nur direkt aus dem Vektor laufen.

template <class T>
class IterImpl
{
public:
    virtual T* next() = 0;
};

template <class T>
class Iter
{
public:
    Iter( IterImpl<T>* pImpl ):mpImpl(pImpl) {};
    Iter( Iter<T>& rIter ):mpImpl(pImpl) 
    {
        rIter.mpImpl = 0; // take ownership
    }
    ~Iter() {
        delete mpImpl; // does nothing if it is 0
    }
    T* next() {
    return mpImpl->next(); 
    }
private:
    IterImpl<T>* mpImpl; 
};

template <class C, class T>
class IterImplStl : public IterImpl<T>
{
public:
    IterImplStl( C& rC )
    :mrC( rC ),
    curr( rC.begin() )
    {}
    virtual T* next()
    {
    if ( curr == mrC.end() ) return 0;
    typename T* pResult = &*curr;
    ++curr;
    return pResult;
    }
private:
    C& mrC;
    typename C::iterator curr;
};


class Widget;

// in the base clase we do not need to include widget
class TestBase
{
public:
    virtual Iter<Widget> getIter() = 0;
};


#include <vector>

class Widget
{
public:
    int px;
    int py;
};

class Test : public TestBase
{
public:
    typedef std::vector<Widget> WidgetVec;

    virtual Iter<Widget> getIter() {
        return Iter<Widget>( new IterImplStl<WidgetVec, Widget>( mVec ) ); 
        }

    void add( int px, int py )
    {
        mVec.push_back( Widget() );
        mVec.back().px = px;
        mVec.back().py = py;
    }
private:
    WidgetVec mVec;
};


void testFn()
{
    Test t;
    t.add( 3, 4 );
    t.add( 2, 5 );

    TestBase* tB = &t;
    Iter<Widget> iter = tB->getIter();
    Widget* pW;
    while ( pW = iter.next() )
    {
        std::cout << "px: " << pW->px << " py: " << pW->py << std::endl;
    }
}

Dies sollte das tun, was Sie wollen:

typedef typename std::vector<T>::iterator MyIterator;

Accelerated C ++ :

  

Wenn Sie eine Art, wie vector<T> haben, die auf einem Template-Parameter abhängig ist, und Sie möchten ein Mitglied dieses Typs verwenden, wie size_type, dass selbst ein Typ, müssen Sie den gesamten Namen vorangestellt von typename zu lassen Sie die Implementierung kennt den Namen als eine Art zu behandeln.

Ich bin nicht sicher, was Sie unter „nicht std :: vector öffentlich aussetzt“, aber in der Tat, können Sie einfach Ihre typedef so definieren:

typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator; // To work with constant references

können Sie diese typedefs ohne dass der Benutzer bemerken etwas später ändern ...

Durch die Art und Weise, wird es als gute Praxis, auch ein paar andere Arten aussetzen, wenn Sie Ihre Klasse wollen als Container verhalten:

typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::difference_type difference_type;
typedef typename std::vector<T>::pointer pointer;
typedef typename std::vector<T>::reference reference;

Und wenn sie von Ihrer Klasse benötigt:

 typedef typename std::vector<T>::const_pointer const_pointer;
 typedef typename std::vector<T>::const_reference const_reference;

Sie werden die Bedeutung all diese finden typedef hier: STL-Dokumentation auf Vektoren

Edit: Hinzugefügt wurde die typename wie in den Kommentaren vorgeschlagen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top