嵌套 class 作为模板参数

Nested class as a template parameter

我尝试编写一个自定义 STL 样式的容器。为了简单起见,假设它是一个列表。我查找了定义此类容器的标准方法:

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

现在,我想使用嵌套 class:

来管理列表的节点
(inside mylist)
class node {
    T data;
    node *next;
}

据我了解,我不需要在 node 的定义前放置一个 template 说明符,因为编译器将实例化单独的 classes mylist<T,A>::node mylist 模板参数的每个组合。

但是,现在我不仅需要为类型 T 本身的数据分配内存,还需要为它们的包装器 node 分配内存。因此,我希望默认模板参数的类型为 std::allocator<mylist<T>::node>。不过,那时 mylist 还没有被声明,编译器很不高兴是可以理解的:

error: `mylist' was not declared in this scope

如何解决这一难题?有两个约束:

I need node to be nested as it needs to access the allocator instance of 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)。

默认分配器的类型参数是什么并不重要,重要的是实际类型。您可以使用 rebind_alloc 来自 std::allocator_traits:

Alloc::rebind<T>::other if present, otherwise Alloc<T, Args> if this Alloc is 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.