【问题标题】:C++ template class T troubleC++模板类T麻烦
【发布时间】:2010-02-22 16:31:51
【问题描述】:
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>*
}

我该怎么做?

【问题讨论】:

  • 你得到的具体错误是什么?
  • 您是否打算将内部 Item 单独作为模板?
  • 语法错误。现在可以了。感谢 Matthieu M.

标签: c++ class templates private


【解决方案1】:

您正在重用T 类型名称。使用不同的: template &lt;class U&gt; struct Item { ... (或从Item 一起删除模板化 - 看起来你对外部模板参数很好):

template <class T>
class List
{
    ...
    protected:

        struct Item
        {
            Item* next;
            T data;
        };

        Item* allocate() { return object; }
};

【讨论】:

  • 为什么这被否决了?这是正确的......也不需要将 Item 声明为模板,因为其目的是重用与类模板实例化时相同的类型。
  • @Nick Meyer:(我没有投反对票。)但是,首先,它没有回答关于课外定义的问题。其次,你怎么知道意图?在 OP 中,Item 是一个独立的嵌套模板,可以在其他上下文中用于其他目的。没有什么说它总是会使用与“外部”类相同的参数来实例化。
  • 那么对嵌套模板使用相同的类型名称有何帮助?
  • 你在说什么名字?参数名称T?它没有帮助。这是一个错误。内部模板中的参数名称必须与外部模板的参数不同。显然,在这种情况下,OP 不仅不知道答案,甚至不知道问题。
【解决方案2】:

方法定义的正确语法是

template <class T>
typename List<T>::Item* List<T>::allocate()
{ 
    ... 
    return object; // struct Item<T>* 
} 

出于某种原因,其他发帖人坚持将&lt;T&gt; 部分附加到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(); 
}; 

【讨论】:

  • 不是必须是List&lt;T&gt;::Item&lt;T&gt;*,因为List和Item都是模板吗?
  • @sepp2k:你是对的。我想我终于把所有的点点滴滴都弄对了。
【解决方案3】:

写:

template <class T>
struct List<T>::Item* List<T>::allocate()
// etc

:: 运算符告诉编译器 Item 是 List 的嵌套类。

【讨论】:

  • 还不正确 :) 应该是List&lt;T&gt;::Item*。此外,可能需要一个额外的typename 关键字(除非struct 使它变得不必要)。附言不,struct 不需要。
【解决方案4】:

问题其实更深:

您不必将Item 声明为template,因为它是模板类中的一个嵌套类,它可以访问T

template <class T>
class List
{
public:

private:
  struct Item { ... };
};

然后你会像这样定义access

template <class T>
typename List<T>::Item List<T>::access(...) {}

这里的重点是List是一个模板类,所以必须指定它的参数,而一旦为List指定了T,就不需要再精确了。

注意typename ;)

【讨论】:

    【解决方案5】:

    您需要限定类型:List::Item&lt;T&gt;

    当你在类声明中,或在类型(或派生类)的每个成员函数的参数列表或主体中时,你可以使用类型的非限定名称,但不能用于返回类型.当编译器解析返回类型时,它还不知道您正在定义 List 模板的成员,因此它不会查看该类范围内的内容。

    这是编译器工作方式的一个有趣点,它实际上影响了即将发布的标准中的一些更改,以允许 auto 之类的返回类型定义:

    template<typename T, typename U>
    auto sum( T lhs, U rhs ) -> delctype(lhs+rhs) 
    { return lhs+rhs; }
    

    一旦参数存在,编译器就能够推断出TU 类型,但是你不能告诉它返回类型是decltype(lhs+rhs) 作为返回类型,因为lhsrhs 都还没有在适用范围。虽然这是一个 C++ 唯一的问题,但它的根源在于您面临的同一个问题:返回类型的范围在被声明的方法的范围之外。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 2017-10-02
      • 1970-01-01
      • 2022-08-10
      • 2012-02-04
      • 1970-01-01
      • 2016-11-07
      相关资源
      最近更新 更多