[英]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:
有两个限制:
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
做到这一点,从而降低node
对A
的参数依赖性,但这对我正在实现的数据结构至关重要。 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, otherwiseAlloc<T, Args>
if thisAlloc
isAlloc<U, Args>
Alloc::rebind<T>::other
如果存在,否则Alloc<T, Args>
如果这个Alloc
是Alloc<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.