Container und Iterator



  • Hallo,

    gibt es in der STL einen Container dessen Iteratoren einfach Pointer sind?

    Also sowas wie

    container<double> c;
    double* iter = c.begin();
    

    Bei Vektoren geht so etwas nicht und bei den anderen Standardcontainern selbstverständlich auch nicht, nur bei tr1::arrays<T,N> sind die Iteratoren so definiert.

    Vielleicht gibt es auch eine Möglichkeit wie man die iteratoren auf pointer abbilden kann, natürlich nur wenn der Container seine Elemente linear speichert...

    Danke



  • Ein Vector-Iterator kann als Pointer definiert sein (ist er in vielen Implementierungen auch), aber Du darfst Dich nicht darauf verlassen. Ganz allgemein gesprochen, nein, gibt es nicht. Selbst bei tr1::array muss es nicht so sein.

    Aber da das Iterator-Konzept ein "abstrahierter Pointer" ist, wieso willst Du überhaupt den umgekehrten Weg gehen?

    Bei std::vector und std:tr1::array kannst Du Dir jedoch einen Pointer auf den zusammenhängenden Bereich holen, mittels &container[0].



  • Was hast du denn genau vor?



  • Einfach mal blind ins blaue:

    double* iter = &(*(c.begin()));
    


  • Ok, es geht um folgendes Problem ( ein Teil von diesem Projekt Numerische Bibliothek):

    template<class ContainerType>
    class ode_step_euler
    {                                                                                  
         ContainerType dxdt;                                                            
    
     public:
    
         template<class CallMethod, class Iterator>
         void do_step( CallMethod deriv , double dt , Iterator start , Iterater end )
         {
             ContainerType::iterator dxdtiter = dxdt.begin();
             deriv( start , dxdtiter );
             while( start != end )
                 *start++ += dt * (*dxdtiter++);
         }
    };
    

    Um diese Klasse zu benutzen, braucht man eine Funktion oder Klasse deriv. Viele Leute sind es gewohnt diese Funktion in der Form

    void deriv( double *x , double *dxdt )
    {
        x[0] = ...;
        x[1] = ...;
    }
    

    zu schreiben, so funktioniert es in den Numerical Recipies, in der gsl... Dann kann die Klasse ode_step_euler zum Beispiel so benutzt werden:

    ode_step_euler<Container> euler;
    Container state;
    for( size_t i=0 ; i<1000 ; ++i )
    {
        euler.do_step( deriv, 0.01 , state.begin() , state.end() );
        // do something with state
    }
    

    Deshalb wäre es gut ein Beispiel zu haben, dass dieser Funktionsaufruf von deriv mit double* immer klappt, d.h. es muss sichergestellt ist, daß die Iteratoren von Containertype in diesem Beispiel pointer sind. Es geht nur um ein Beispiel, um zu zeigen wie man die Klasse ode_step_euler benutzt mit pointern benutzt.



  • Der STL-Container std::vector garantiert dir, dass alle Elemente an einem Stück in einem dynamischen Array stehen. Dadurch gilt &v[n] == &v[0] + n für gültige n . Somit kannst du mit relativ wenig Aufwand entsprechende Umwandlungsfunktionen schreiben. Sogar Const-Correctness kann berücksichtigt werden:

    template <typename T>
    T* ptr_begin(std::vector<T>& vec)
    {
    	return &vec[0];
    }
    
    template <typename T>
    const T* ptr_begin(const std::vector<T>& vec)
    {
    	return &vec[0];
    }
    
    template <typename T>
    T* ptr_end(std::vector<T>& vec)
    {
    	return &vec[0] + vec.size();
    }
    
    template <typename T>
    const T* ptr_end(const std::vector<T>& vec)
    {
    	return &vec[0] + vec.size();
    }
    

    Die Anwendung ist dann superleicht:

    euler.do_step(deriv, 0.01, ptr_begin(state), ptr_end(state));
    

Anmelden zum Antworten