2012-04-07 4 views
0

Ich lese jetzt "C++ Standard Library". Und ich finde etwas verwirrt in Kapitel 5.7. Wie wir wissen, können wir unsere eigenen Funktionen und Algorithmen schreiben, um Elemente von Sammlungen zu verarbeiten. Natürlich können diese Operationen auch generisch sein. Sehen wir uns ein Beispiel an.Der folgende Code definiert eine generische Funktion, die eine optionale Zeichenfolge gefolgt von allen Elementen des übergebenen Containers ausgibt.C++: Verwenden Sie benutzerdefinierte generische Funktionen

template <class T> 
inline void PRINT_ELEMENTS(const T& col1,const char *optcstr = "") 
{ 
    typename T::const_iterator pos; 
    for(pos = col1.begin();pos != col1.end();++pos) 
     cout << *pos << " "; 
    cout << endl; 
} 

Und po wird als mit der Iteratortyp des übergebenen Containertypen deklariert, typyname ist notwendig angeben, dass const_iterator ein Typ ist und nicht ein Wert vom Typ T.

ich einige Fragen:

(1) Wenn ich Typname löschen im Code, es funktioniert gut. Siehe folgenden Code:

#include <iostream> 
#include <vector> 
#include <set> 
#include <algorithm> 

using namespace std; 

int square (int value) 
{ 
    return value*value; 
} 

template <class T> 
inline void PRINT_ELEMENTS(const T& col1,const char *optcstr = "") 
{ 
    /*typename T::const_iterator pos;*/ 
    T::const_iterator pos; 

    for(pos = col1.begin();pos != col1.end();++pos) 
     cout << *pos << " "; 
    cout << endl; 
} 

int main() 
{ 
    set<int> coll1; 
    vector<int> coll2; 

    // insert elements from 1 to 9 into coll1 
    for (int i=1; i<=9; ++i) { 
     coll1.insert(i); 
    } 
    /*PRINT_ELEMENTS(coll1,"initialized: ");*/ 

    // transform each element from coll1 to coll2 
    // - square transformed values 
    transform (coll1.begin(),coll1.end(), // source 
        back_inserter(coll2), // destination 
        square);      // operation 

    PRINT_ELEMENTS(coll2,"squared:  "); 
} 

Es funktioniert well.Its Ausgabe lautet: enter image description here

Warum ist Typname nicht notwendig? Und ich verstehe seine Funktion hier nicht sehr. Könnte mir jemand interpretieren?

(2) Warum konnte ich nicht verwenden Vektor :: Iterator zur Ausgabe der Elemente wie folgt aus:

#include <iostream> 
#include <set> 
#include <vector> 
#include <algorithm> 
using namespace std; 

int main() 
{ 
    set<int> intSet; 
    vector<int> intVector2; 

    for (int i = 1;i <= 10;++i) 
     intSet.insert(i); 

    transform(intSet.begin(),intSet.begin(), 
     back_inserter(intVector2), 
     negate<int>()); 

    vector<int>::iterator iter = intVector2.begin(); 
    for(;iter != intVector2.end();++iter) 
     cout << *iter << endl; 
} 

Es gibt nothing.I Visual Studio 2008 verwenden, um meine Code auszuführen. Könnte mir jemand helfen? Vielen Dank.

Antwort

4

typename ist nicht erforderlich, weil einige Versionen von Visual Studio nicht dem Standard entsprechen. Neuere Versionen und andere Compiler sind diesbezüglich strenger und Ihr Code wird dort nicht kompiliert.

Ihr zweites Beispiel funktioniert nicht, weil Sie begin() und begin(), nicht begin() und end() bestanden haben.

transform(intSet.begin(),intSet.begin(), 

Whoops.

0

(1)

typename hilft seinen Operanden als eine Art in bestimmten Situationen disambiguieren.

Am bekanntesten scheint im Rahmen einer Klassendeklaration zu sein:

class X 
{ 
    ... 
    typename Y::Z w; // necessary 
}; 

(2)

Es ist ein Tippfehler ...

- transform(intSet.begin(),intSet.begin(), 
    back_inserter(intVector2), 
    negate<int>()); 


+ transform(intSet.begin(),intSet.end(), 
    back_inserter(intVector2), 
    negate<int>());