2010-03-23 2 views
5

У меня есть шаблон Вершины в vertex.h. На моем графике.:Что делает этот «декларант недействительным»? C++

20 template<class edgeDecor, class vertexDecor, bool dir> 
21 class Vertex; 

, который я использую в своем графическом шаблоне.

Я успешно использовал шаблон Вершины по всему графику, обратил указатели на вершины и т. Д. Теперь я впервые пытаюсь объявить и создать экземпляр объекта Вершины, а gcc сообщает мне, что мой «декларатор» 'инвалид'. Как это может быть?

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 }; 

И НКУ говорит:

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 

Я знаю, что это, вероятно, еще один нуб вопрос, но я буду признателен за любую помощь.

+0

Возможно, это не связано с этой проблемой, но вы уверены, что хотите «= новый Vertex (INT_MAX)»? Возможно, вы имели в виду «вершину», некапитализированную (что я предполагаю, это typedef)? Также Vertex <...> действительно имеет ctor с указателем вершин/вершин? –

ответ

1

Игорь прав. Что касается следующей ошибки:

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

... Вы, вероятно, нужно сказать:

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

Это решило. Благодарю. –

4

Вероятно, должно быть

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

, потому что вы объявляете экземпляр Vertex. typename ключевое слово действует только в списке параметров шаблона.

Благодаря Абхай и outis за указание на допустимые виды использования keyword вне списка параметров шаблона.

После того, как еще раз взглянуть на код и ряд других вещей приходят на ум:

  1. Как отметил Майк Dinsdale вам не хватает параметров шаблона здесь: new Vertex(INT_MAX);. Вместо этого попробуйте Vertex<edgeDecor,int,dir>.
  2. Вы назначаете указатель на экземпляр класса. Если вы создаете его в стеке, это должно быть примерно так:

    Vertex v (INT_MAX);

При создании в куче v должен быть тип указателя:

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

«ключевое слово typename допустимо только в списке параметров шаблона шаблона», я так не думаю. Для имен, зависящих от шаблонов, большинству компиляторов требуется указать * typename *. – Abhay

+0

RE зависимые имена: читайте http://pages.cs.wisc.edu/~driscoll/typename.html. В случае OP 'Vertex ' не является зависимым именем, поэтому 'typename' недопустим. – outis

+0

Без ключевого слова "typename" gcc дает: graph.h: 88: error: ожидаемый тип-спецификатор перед 'Vertex' Что заставляет меня думать, что здесь требуется «typename», чтобы указать компилятору, что я имею в виду к типу. –

0

Как уже говорилось, это проблема неуместна typename первой.

Некоторые примеры:

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

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

Использование MyClass:

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

Там нет необходимости typename, потому что нет никакой двусмысленности, компилятор знает MyClass должен быть тип здесь.

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

Мы должны неоднозначность, поскольку компилятор не знает заранее, если Foo символ будет тип, метод или атрибут. Действительно, если T == int этот код ошибочен, так как Foo будет представлять атрибут static вместо struct!

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

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

Здесь typename не требуется: поскольку компилятор знает все типы в списке параметров шаблона, он может создать экземпляр класса шаблона для MyClass<int> и MyClass<float> и, как для обычного класса знает изнанку каждого экземпляра (и, в частности, что представляет собой каждый символ).

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

Еще раз нам нужно typename потому Foo тип и компилятор должен знать это.

Если вы действительно этого не понимаете, не беспокойтесь. Ключевое слово typename и template иногда ползут в необычных местах в общем коде: просто подождите, пока начнется ошибка компилятора, вы скоро запомните ошибки и исправьте их в подмигивании.

Смежные вопросы