C++模板类T的麻烦

发布于 2024-08-22 16:08:57 字数 478 浏览 4 评论 0原文

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

我怎样才能做到这一点?

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

how can i do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

私野 2024-08-29 16:08:57

您正在重复使用 T 类型名称。使用不同的:
模板struct Item { ... (或从 Item 中删除模板化 - 看起来您对外部模板参数很好):

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

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

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

You are reusing the T type name. Use a different one:
template <class U> struct Item { ... (or remove templatization from Item all together - it looks like you are just fine with outer template parameter):

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

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

        Item* allocate() { return object; }
};
一个人的夜不怕黑 2024-08-29 16:08:57

方法定义的正确语法是

template <class T>
typename List<T>::Item* List<T>::allocate()
{ 
    ... 
    return object; // struct Item<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(); 
}; 

The correct syntax for method definition is

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

For some reason other posters insisted on attaching the <T> part to Item instead of List (tricked by your original version, apparently).

Sorry, I haven't noticed that Item is also a tempate by itself. In that case it has to be

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

However, note that it is illegal to re-use the same parameter name in the inner template declaration!!! Your original class definition is illegal. It has to be changed to something like

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(); 
}; 
无法回应 2024-08-29 16:08:57

写入:::

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

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

Write:

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

The :: operator tells the compiler that Item is a nested class of List.

夢归不見 2024-08-29 16:08:57

事实上,问题更深层:

您不必将 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 指定的,无需再次精确。

注意类型名称;)

The problem is deeper in fact:

You don't have to declare Item as being template, because it's a nested class within a template class it has access to T.

template <class T>
class List
{
public:

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

And then you would define access like so:

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

The point here is that List is a template class, so its parameters must be specified, while once T is specified for List it's not necessary to precise it once again.

Note typename ;)

§对你不离不弃 2024-08-29 16:08:57

您需要限定类型:List::Item

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

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

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

编译器能够推导出类型 T 和U 一旦参数存在,但你不能告诉它返回类型是 decltype(lhs+rhs) 作为返回类型,因为 lhs rhs 都尚未在范围内。虽然这只是 C++ 的问题,但它的根源与您面临的问题相同:返回类型的范围位于所声明的方法的范围之外。

You need to qualify the type: List::Item<T>

You can use the non-qualified name of the type when you are inside the class declaration, or inside the argument list or body of each of the member functions of the type (or derived classes), but not for the return type. When the compiler resolves the return type, it does not yet know that you are defining a member of the List template, and as such it will not look inside that class scope.

This is an interesting point of how compilers work that has actually influenced some changes in the upcoming standard to allow auto like return type definitions:

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

The compiler is able to deduce types T and U once the arguments are present, but you cannot tell it that the return type is decltype(lhs+rhs) as return type since neither lhs nor rhs are yet in scope. While this is a C++ only problem, it has its roots in the same problem you are facing: the scope of the return type is external to the scope of the method that is being declared.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文