我尝试编写一个自定义STL样式的容器。为简单起见,我们说它是一个列表。我查找了定义这样一个容器的标准方法:
template <typename T, typename A = std::allocator<T> > class mylist;
现在,我想使用嵌套类来管理列表的节点:
(inside mylist)
class node {
T data;
node *next;
}
我的理解是,我不需要在template
的定义前放置node
说明符,因为编译器将为{{1}的每个组合实例化单独的类mylist<T,A>::node
模板参数。
但是,现在我需要为类型mylist
本身的数据分配内存,而且还需要为它们的包装器T
分配内存。因此,我希望默认模板参数的类型为node
。但是,那时,std::allocator<mylist<T>::node>
尚未被声明,编译器可以理解为难以理解:
mylist
如何解决这个难题?有两个限制因素:
error: `mylist' was not declared in this scope
,因为它需要访问node
的分配器实例。例如,我在mylist
上声明operator=
,其中大量内存管理以递归方式发生。对于列表而言这可能有点过分,您可以在node
内执行此操作,从而降低mylist
对node
的参数依赖性,但这对我正在实现的数据结构至关重要。 答案 0 :(得分:2)
默认分配器的类型参数是什么,只是实际类型无关紧要。您可以使用std::allocator_traits
中的rebind_alloc
:
Alloc::rebind<T>::other
如果存在,否则Alloc<T, Args>
如果此Alloc
为Alloc<U, Args>
得到你需要的东西:
template <typename T, typename A = std::allocator<T> >
class mylist {
class node { ... };
using NodeAlloc = typename std::allocator_traits<A>::template rebind_alloc<node>;
};
然后使用NodeAlloc
获取node
。这样,如果用户未指定分配器,您将获得默认的std::allocator<T>
,然后使用std::allocator<node>
。这正是您想要的,而不必公开node
。
答案 1 :(得分:1)
我需要嵌套节点,因为它需要访问
的分配器实例mylist
不要太确定。他们可以成为朋友:
template <typename, class> class list;
template <typename T>
struct node {
// ...
};
template <typename T, class Alloc=std::allocator<T> >
class list {
friend node<T>;
// ...
};
如果您不想在文件之外访问node
,请在头文件(.h
/ .hpp
)中省略它。