我在链表类中定义了以下函数。头文件中的声明如下所示:
template <typename T>
class RingBuffer
{
...//stuff
static BLink * NewLink (const T&); // allocator
};
BLink是RingBuffer类中的“链接”类。以下实现代码:
template <typename T>
RingBuffer<T>::BLink * RingBuffer<T>::NewLink( const T& t ) // this is line 114
{
// create a new link in linked list
....
....
}
给我这个编译错误:
./ ringbuff.cpp:114:错误:在'令牌
之前的预期构造函数,析构函数或类型转换我很难过为什么在返回值之前它需要一个预期的构造函数,析构函数或类型转换。
答案 0 :(得分:5)
这里的问题是你指的是一个嵌套的依赖类型名称(即BLink嵌套在RingBuffer中,它取决于模板参数)
在这种情况下,您需要通过声明RingBuffer<T>::BLink
是实际的类型名称来帮助您的编译器。您可以使用typename
关键字来执行此操作。
template <typename T>
typename RingBuffer<T>::BLink * RingBuffer<T>::NewLink(const T& t)
{
// ...
}
在模板参数RingBuffer<T>::BLink
已知之前,编译器无法知道T
是类型名称还是静态成员。当编译器解析您的函数模板时,T
未知,解决歧义的规则是默认为“这不是类型名称”。
另一个简短的例子(公然抄袭Scott Meyers的Effective C ++):
template<typename C>
void print2nd(const C& container)
{
C::const_iterator * x;
…
}
这可能会更好地说明问题,因为它更紧凑。正如已经说过的那样,解析器不清楚C :: const_iterator是一个类型名还是一个静态数据成员,因为它在解析这部分代码时不知道C
是什么(它可能在稍后实际模板化时的时间点)。因此,为了简化编译器实现者的生活,这种歧义被解析为“不是类型名称”,如果程序员想要使用嵌套在依赖于模板参数的任何内容的类型名称,他/她必须使用{{ 1}}关键字在名称前面让编译器知道它应该被视为类型名称。
不幸的是,在基类列表中使用嵌套依赖类型名称或成员初始化列表中的基类标识符时,该规则有一个例外。
typename
顺便说一下:您应该将控制台客户端的字符集设置为UTF-8,这样您就可以获得template<typename T>
struct Base {
struct Nested {
Nested(int) {}
};
};
template<typename T>
struct Derived : public Base<T>::Nested { // typename not allowed here
Derived(int i)
: Base<T>::Nested(i) // nor here
{}
};
而不是‘*’
。
答案 1 :(得分:0)
编译器消息有点误导。 基本上表示语法/解析错误。 确保原型在编译文件中可见,确保将环形缓冲区声明为模板。正如其他人所说,在课后宣布检查半栏。