template <class T>
class List
{
public:
List();
~List();
...
protected:
template <class T> struct Item
{
struct Item* next;
T data;
};
...
struct Item<T>* allocate();
};
template <class T>
struct Item<T>* List<T>::allocate() // error here
{
...
return object; // struct Item<T>*
}
我该怎么做?
答案 0 :(得分:3)
您正在重复使用T
类型名称。使用另一个:
template <class U> struct Item { ...
(或者从Item
一起移除模板化 - 看起来你对外模板参数没问题了):
template <class T>
class List
{
...
protected:
struct Item
{
Item* next;
T data;
};
Item* allocate() { return object; }
};
答案 1 :(得分:3)
方法定义的正确语法是
template <class T>
typename List<T>::Item* List<T>::allocate()
{
...
return object; // struct Item<T>*
}
出于某种原因,其他海报坚持将<T>
部分附加到Item
而不是List
(显然是由原始版本欺骗)。
抱歉,我没有注意到Item
本身也是一种诱惑。在那种情况下,它必须是
template <class T>
typename List<T>::template Item<T>* List<T>::allocate()
{
...
return object; // struct Item<T>*
}
但请注意,在内部模板声明中重复使用相同的参数名称是违法的!您原来的班级定义是非法的。它必须改为
template <class T>
class List
{
...
template <class U> struct Item // Note: `U` used intead of `T`
{
struct Item* next;
U data;
};
...
struct Item<T>* allocate();
};
答案 2 :(得分:2)
写:
template <class T>
struct List<T>::Item* List<T>::allocate()
// etc
::运算符告诉编译器Item是嵌套的List类。
答案 3 :(得分:1)
您需要限定类型:List::Item<T>
。
当您在类声明中时,或者在类型(或派生类)的每个成员函数的参数列表或主体内部时,可以使用该类型的非限定名称,但不能用于返回类型。当编译器解析返回类型时,它还不知道您正在定义List
模板的成员,因此它不会查看该类范围。
这是一个有趣的观点,编译器如何工作实际上影响了即将推出的标准中的一些变化,以允许auto
像返回类型定义:
template<typename T, typename U>
auto sum( T lhs, U rhs ) -> delctype(lhs+rhs)
{ return lhs+rhs; }
一旦参数存在,编译器就能够推断出类型T
和U
,但你不能告诉它返回类型是decltype(lhs+rhs)
作为返回类型,因为它们都不是{{1 }} lhs
还在范围内。虽然这只是一个C ++问题,但它的根源在于您面临的同一个问题:返回类型的范围是在声明的方法范围之外。
答案 4 :(得分:1)
事实上问题更严重:
您不必将Item
声明为template
,因为它是模板类中的嵌套类,可以访问T
。
template <class T>
class List
{
public:
private:
struct Item { ... };
};
然后你会像这样定义access
:
template <class T>
typename List<T>::Item List<T>::access(...) {}
这里的要点是List
是模板类,因此必须指定其参数,而为T
指定List
后,则无需再次对其进行精确处理。< / p>
注意typename
;)