Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Eigene Funktion mit Iteratoren

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
19.10.2003, 21:14 Uhr
(un)wissender
Niveauwart


Wie erstelle ich eigene Funktionen mit Iteratoren?
Ungefär so:


C++:
template<typename iter>
    void swap(iter elem_one, iter elem_two)
    {        
        iter temp   = *elem_one;
        *elem_one = *elem_two;
        *elem_two = temp;
    }



Das funktioniert natürlich so nicht, wie müsste es aussehen, dass es z.B. für char* etc. funktioniert?
Mir fehlt echt der Plan...
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
19.10.2003, 22:48 Uhr
0xdeadbeef
Gott
(Operator)


Doch, das funktioniert genau so.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
19.10.2003, 23:05 Uhr
(un)wissender
Niveauwart


Nee, das geht leider genauso nicht!
Habe es ausprobiert, das würde z.B. für char * stehen


C++:
void swap(char *elem_one, char *elem_two)
{
char *temp = *elem_one; //Fehler: char * = char
*elem_one = *elem_two;
*elem_two = temp; //Fehler: char = char*??

}



In der STL machen die das irgendwie anders, mit valueType, difference, etc.
habe das aber nicht verstanden.
Es muss aber funktionieren, schließlich funktionieren ja die STL_Algorithmen mit Iteratoren wie mit Pointern.
Ich will das auch.

Ich glaube, hier ist virtual gefragt, wo ist der eigentlich, Urlaub ist hiermit abgelehnt...
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
20.10.2003, 00:30 Uhr
virtual
Sexiest Bit alive
(Operator)


Stichwort sind hier die Templates iterator und iterator_traits.
Ein nicht trivialer Iterator (also etwas, was kein Pointer ist), sollte vom Template iterator abgeleitet werden. Dieses Template ist recht simple, es definiert 5 Iterator specifische Typen:

C++:
template <class C, class T, class D = ptrdiff_t, class P = T*, class R = T&>
struct iterator
{
    typedef C iterator_category; // Typ des Iterators: forward, bidir, random ...
    typedef T value_type; // Der Typ vom Element, das dem Iterator zugrunde liegt
    typedef D difference_type; // Typ, um Abstände zu messen
    typedef P pointer; // Zeiger auf value_type (in der Regel)
    typedef R reference; // Reference auf value_type (in der Regel)
}


Ziel dieser Klasse ist es, für alle Iteratoren die gleichen Typ namen zu definieren. Egal, ob Du nun ein std::set<std::string> oder ein std::list<std::string> nimmst: in beiden Fällen gibt es einen Iterator (der meist nicht trivial ist) und dieser Iterator hat einen Typen value_type, der ein std::string ist, vereinfacht ausgedrückt:

C++:
std::string == typename std::list<std::string>::iterator::value_type
std::string == typename std::set<std::string>::iterator::value_type


Übertragen auf Deine Routine könnte man also in erster (!) Näherung schreiben:

C++:
template<typename iter>
void swap(iter elem_one, iter elem_two)
{        
    [b]typename iter::value_type[/b] temp   = *elem_one;
    *elem_one = *elem_two;
    *elem_two = temp;
};


Würde sogar manchmal Funktionieren; nämlich genau dann, wenn Du einen Iterator hast, der von og Template geerbt hat.
Nun gilt das Iteratorkonzept aber nicht nur für die Klassen, die von iterator abgelitten sind, sondern auch für so triviale Dinge wie einen Pointer. Nur dummerweise würde die Lösung, die ich grade für das swap nannte, genau hier versagen: ein Pointer hat nunmal keinen value_type.
Wie viele andere Probleme in der Informatik auch, wird das Problem durch eine Indirektion gelöst: Wir definieren kurzerhand ein Template, welches die Characteristika eines Iterators beschreibt, die iterator_traits:

C++:
template <I>
struct iterator
{
    typedef typename I::iterator_category iterator_category;
    typedef typename I::value_type value_type;
    typedef typename I::difference_type difference_type;
    typedef typename I::pointer pointer;
    typedef typename I::reference reference;
};


Als Template parameter - so suggeriert diese Definition - wird immer ein iterator erwartet, und wir definieren exakt die gleichen Typen nochmal, diesmal eben in iterator_traits. Der wesentliche Unterschied ist einfach, daß in diesem Template als Parameter ein Iterator übergeben wird, und nicht, wie beim iterator Template selbst, fünf typen.
Um nun auch mit Zeigern klarzukommen, wenden wir die partielle Templatespezialisierung an:

C++:
template<class T> iterator_traits<T*>
{
    typedef std::rand_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef T* pointer;
    typedef T&reference;
};


Nun haben wir also nicht nur für von iterator abgelittene Klassen iterator_traits, sondern auch für Pointer (und damit eigentlich für alle Iteratoren. folgerichtig verwendet man die iterator_traits dann auch in seiner Funktion:

C++:
template<typename iter>
void swap(iter elem_one, iter elem_two)
{        
    [b]typename std::iterator_traits<iter>::value_type[/b] temp   = *elem_one;
    *elem_one = *elem_two;
    *elem_two = temp;
};


Ich denke, so sollte es gehen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 20.10.2003 um 00:32 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
20.10.2003, 06:53 Uhr
(un)wissender
Niveauwart


Ha, danke für deine ausfürliche Antwort!
Genau so geht das!
Ich dachte mir sowas schon, habe es aber nicht ganz hinbekommen, viel zu kompliziert gedacht...
Welchen Header muss man includieren für iterator_traits?
Ist es #include<iterator>, mit dem habe ich es gemacht.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
20.10.2003, 08:12 Uhr
virtual
Sexiest Bit alive
(Operator)


Ja.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
20.10.2003, 09:13 Uhr
(un)wissender
Niveauwart


Kurz und knapp, wenn es geht, ausfürlich wenn es muß.

--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: