C ++模板类T麻烦

时间:2010-02-22 16:31:52

标签: c++ class templates private

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

我该怎么做?

5 个答案:

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

一旦参数存在,编译器就能够推断出类型TU,但你不能告诉它返回类型是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;)