简体   繁体   English

嵌套类作为模板参数

[英]Nested class as a template parameter

I try to write a custom STL-style container. 我尝试编写一个自定义STL样式的容器。 For the sake of simplicity, let's say it's a list. 为简单起见,我们说它是一个列表。 I looked up the standard way to define such a container: 我查找了定义这样一个容器的标准方法:

template <typename T, typename A = std::allocator<T> > class mylist;

Now, I want to manage the nodes of the list using a nested class: 现在,我想使用嵌套类来管理列表的节点:

(inside mylist)
class node {
    T data;
    node *next;
}

It is my understanding that I need not put a template specifier in front of the definition of node as the compiler will instantiate separate classes mylist<T,A>::node for each combination of mylist 's template parameters. 我的理解是,我不需要在node定义之前放置template说明符,因为编译器将为mylist的模板参数的每个组合实例化单独的类mylist<T,A>::node

However, now I need to allocate memory not only for the data of type T itself, but also for their wrapper node . 但是,现在我需要为T本身的数据分配内存,而且还需要为它们的包装器node分配内存。 Thus, I would like the default template parameter to be of type std::allocator<mylist<T>::node> . 因此,我希望默认模板参数的类型为std::allocator<mylist<T>::node> At that point, though, mylist has not yet been declared and the compiler is understandably upset: 那时, mylist还没有被声明,编译器可以理解为难过:

error: `mylist' was not declared in this scope

How would one resolve this conundrum? 如何解决这个难题? There are two constraints: 有两个限制:

  • Normally, I would declare the missing class without fully declaring its contents. 通常情况下,我会在没有完全声明其内容的情况下声明缺少的类。 However, since it is nested inside the very thing I want to declare, this is not an option. 但是,因为它嵌套在我想要声明的内容中,所以这不是一个选项。
  • I need node to be nested as it needs to access the allocator instance of mylist . 我需要嵌套node ,因为它需要访问mylist的分配器实例。 Eg, I have operator= declared on node where a lot of memory management happens recursively. 例如,我在node上声明了operator= ,其中大量内存管理以递归方式发生。 This might be overkill for a list and you could do that from within mylist , thereby dropping the parametric dependence of node on A , but it is crucial for the data structure I'm implementing. 对于列表来说这可能是过度的,你可以从mylist做到这一点,从而降低nodeA的参数依赖性,但这对我正在实现的数据结构至关重要。

It doesn't matter what the default allocator's type argument is, just the actual type. 默认分配器的类型参数是什么,只是实际类型并不重要。 You can use rebind_alloc from std::allocator_traits : 您可以使用std::allocator_traits rebind_alloc

Alloc::rebind<T>::other if present, otherwise Alloc<T, Args> if this Alloc is Alloc<U, Args> Alloc::rebind<T>::other如果存在,否则Alloc<T, Args>如果这个AllocAlloc<U, Args>

to get what you need: 得到你需要的东西:

template <typename T, typename A = std::allocator<T> >
class mylist {
    class node { ... };

    using NodeAlloc = typename std::allocator_traits<A>::template rebind_alloc<node>;
};

And then use NodeAlloc to get your node s. 然后使用NodeAlloc获取node In this way, if the user doesn't specify an allocator, you would get the default std::allocator<T> and then use std::allocator<node> . 这样,如果用户没有指定分配器,您将获得默认的std::allocator<T> ,然后使用std::allocator<node> This is precisely what you want, without having to expose node . 这正是您想要的,无需暴露node

I need node to be nested as it needs to access the allocator instance of mylist 我需要嵌套节点,因为它需要访问mylist的分配器实例

Don't be so sure. 不要那么肯定。 They can be friends: 他们可以成为朋友:

template <typename, class> class list;

template <typename T>
struct node {
    // ...
};

template <typename T, class Alloc=std::allocator<T> >
class list {
    friend node<T>;
    // ...
};

If you don't want node to be accessible outside of your file, just omit it in your header file ( .h / .hpp ). 如果您不希望在文件外部访问node ,只需在头文件( .h / .hpp )中省略它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM