2010-03-23 14 views
5

Ich habe Vertex Vorlage in vertex.h. Von meinem graph.h:Was macht diesen "Deklarator ungültig"? C++

die ich in meiner Diagrammschablone verwende.

Ich habe die Vertex-Vorlage in meinem Graph erfolgreich verwendet, gebe Zeiger auf Scheitelpunkte usw. zurück. Jetzt versuche ich zum ersten Mal ein Vertex-Objekt zu deklarieren und zu instanziieren, und GCC sagt mir, dass mein 'Deklarator' ist 'ungültig'. Wie kann das sein?

81 template<class edgeDecor, class vertexDecor, bool dir> 
82 Graph<edgeDecor,int,dir> Graph<edgeDecor,vertexDecor,dir>::Dijkstra(vertex s, bool print = false) const 
83 { 
84 /* Construct new Graph with apropriate decorators */ 
85 Graph<edgeDecor,int,dir> span = new Graph<edgeDecor,int,dir>(); 
86 span.E.reserve(this->E.size()); 
87 
88 typename Vertex<edgeDecor,int,dir> v = new Vertex(INT_MAX); 
89 span.V = new vector<Vertex<edgeDecor,int,dir> >(this->V.size,v); 
90 }; 

Und gcc sagt:

graph.h: In member function ‘Graph<edgeDecor, int, dir> Graph<edgeDecor, vertexDecor, dir>::Dijkstra(Vertex<edgeDecor, vertexDecor, dir>, bool) const’: 
graph.h:88: error: invalid declarator before ‘v’ 
graph.h:89: error: ‘v’ was not declared in this scope 

Ich weiß, diese Frage wahrscheinlich eine andere Noob ist, aber ich werde jede Hilfe dankbar.

+0

Wahrscheinlich für dieses Problem nicht verwandt, aber sind Sie sicher, dass Sie möchten, dass „= new Vertex (INT_MAX)“? Hast du vielleicht "unkapitalisiert" gemeint (was ich für ein Typdef halte)? Hat Vertex <...> wirklich einen ctor, der einen Vertex/Vertex-Zeiger nimmt? –

Antwort

1

Igor ist richtig. Wie für die folgenden Fehler:

graph.h:88: error: expected type-specifier before ‘Vertex’ 

... müssen Sie wahrscheinlich sagen:

Vertex<edgeDecor,int,dir> v = new Vertex<edgeDecor,int,dir>(INT_MAX); 
+0

Das hat es gelöst. Vielen Dank. –

4

braucht Wahrscheinlich

Vertex<edgeDecor,int,dir> v = new Vertex(INT_MAX); 

sein, weil Sie eine Instanz von Vertex deklarieren. typename Das Schlüsselwort ist nur in der Vorlagenparameterliste gültig.

Dank Abhay und Outis für gültige Verwendungen von keyword außerhalb der Vorlage Parameterliste Hinweis. eine Reihe anderer Dinge in den Sinn kommen

Nachdem er einen anderen Blick auf den Code mit:

  1. Wie von Mike Dinsdale Sie fehlen Template-Parameter hier: new Vertex(INT_MAX);. Versuchen Sie stattdessen Vertex<edgeDecor,int,dir>.
  2. Sie weisen einer Klasseninstanz einen Zeiger zu. Wenn Sie es auf dem Stapel erstellen, sollte es in etwa so aussehen:

    Vertex v (INT_MAX);

Wenn auf dem Heap zu schaffen v muss Zeigertyp sein:

Vertex<edgeDecor,int,dir>* v = new Vertex<edgeDecor,int,dir>(INT_MAX); 
+2

"typename Schlüsselwort ist nur gültig innerhalb der Vorlage Parameterliste", denke ich nicht. Bei Vorlagen-abhängigen Namen müssen die meisten Compiler * typename * angeben. – Abhay

+0

RE abhängig Namen: lesen http://pages.cs.wisc.edu/~driscoll/typename.html. Im Fall des OP ist 'Vertex ' kein abhängiger Typname, daher ist 'typname' nicht gültig. – outis

+0

Ohne das "typename" -Schlüsselwort gibt gcc: graph.h: 88: Fehler: erwarteter Typspezifizierer vor 'Vertex' Was mich denken lässt "typename" wird hier benötigt, um dem Compiler anzuzeigen, dass ich mich beziehe zu einem Typ. –

0

Wie gesagt, es ist ein Problem der fehl am Platz typename erste ist.

Einige Beispiele:

template <class T> 
struct MyClass 
{ 
    struct Foo { static int MBar; }; 
}; 

template <> 
struct MyClass<int> { static int Foo; }; 

Mit MyClass:

template <class T> 
void useMyClass(T t) 
{ 
    MyClass<T> c; 
} 

Es besteht keine Notwendigkeit von typename ist, weil es keine Zweideutigkeit ist, der Compiler weiß MyClass bekam hier eine Art zu sein.

template <class T> 
void useFoo(T t) 
{ 
    typename MyClass<T>::Foo f; 
} 

Wir müssen eindeutig zu machen, da der Compiler nicht im Voraus nicht wissen, ob das Foo Symbol wird ein Typ, ein Verfahren oder ein Attribut sein. Denn wenn T == int ist dieser Code fehlerhaft, da Foo ein static Attribut anstelle des Seins ein struct darstellen würde!

void useFoo(int t) 
{ 
    int f = MyClass<int>::Foo; 
} 

void useFoo(float t) 
{ 
    float f = MyClass<float>::Foo::MBar; 
} 

Hier typename nicht erforderlich ist: da der Compiler alle Typen in der Vorlage Parameterliste kennt, kann er die Template-Klasse für MyClass<int> und MyClass<float> und wie für eine reguläre Klasse kennt das von innen nach außen aus jeder Instanziierung instanziiert (und insbesondere, was jedes Symbol darstellt).

template <class T> 
void useBar(T t) 
{ 
    int i = typename MyClass<T>::Foo::MBar; 
} 

Wieder einmal müssen wir typename weil Foo ein Typ ist und der Compiler muss es wissen.

Wenn Sie nicht wirklich raus, keine Sorge. Die typename und template Schlüsselwörter manchmal an ungewöhnlichen Orten in generischem Code einschleichen: nur warten, bis der Compiler-Fehler zu beginnen, Sie werden bald die Art von Fehlern speichern und sie in einem Zwinkern korrigieren.