我在vertex.h中有顶点模板。从我的graph.h:
20 template<class edgeDecor, class vertexDecor, bool dir>
21 class Vertex;
我在我的Graph模板中使用。
我在整个Graph中成功使用了Vertex模板,返回指向Vertices的指针等。现在我第一次尝试声明并实例化一个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 };
gcc说:
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
我知道这可能是另一个noob问题,但我会感激任何帮助。
答案 0 :(得分:4)
可能需要
Vertex<edgeDecor,int,dir> v = new Vertex(INT_MAX);
因为您声明了Vertex
的实例。 typename
关键字仅在模板参数列表中有效。
感谢 Abhay 和 outis 指出模板参数列表之外的keyword
的有效使用。
在再看一下代码之后,我想到了其他一些事情:
new Vertex(INT_MAX);
。请改为Vertex<edgeDecor,int,dir>
。您正在指定一个类实例的指针。如果你在堆栈上创建它应该是这样的:
Vertex v(INT_MAX);
如果在堆v
上创建必须是指针类型:
Vertex<edgeDecor,int,dir>* v = new Vertex<edgeDecor,int,dir>(INT_MAX);
答案 1 :(得分:1)
graph.h:88: error: expected type-specifier before ‘Vertex’
......你可能需要说:
Vertex<edgeDecor,int,dir> v = new Vertex<edgeDecor,int,dir>(INT_MAX);
答案 2 :(得分: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
关键字有时会在通用代码中的不寻常位置蔓延:只需等待编译器错误开始,您很快就会记住这类错误并在眨眼中纠正它们。 / p>