【问题标题】:Nested class as a template parameter嵌套类作为模板参数
【发布时间】:2015-11-12 17:18:09
【问题描述】:

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

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

现在,我想使用嵌套类来管理列表的节点:

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

据我了解,我不需要在 node 的定义前面放置 template 说明符,因为编译器将为 mylist 的模板参数的每个组合实例化单独的类 mylist&lt;T,A&gt;::node

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

error: `mylist' was not declared in this scope

如何解决这个难题?有两个限制:

  • 通常,我会在不完全声明其内容的情况下声明缺失的类。但是,由于它嵌套在我要声明的内容中,所以这不是一个选项。
  • 我需要嵌套node,因为它需要访问mylist 的分配器实例。例如,我在node 上声明了operator=,其中很多内存管理都是递归发生的。这对于列表来说可能是多余的,您可以在mylist 中执行此操作,从而消除nodeA 的参数依赖性,但这对于我正在实现的数据结构至关重要。

【问题讨论】:

  • 看看g++是如何实现std::list的可能值得一看。
  • 看分配器rebind

标签: c++ templates stl containers


【解决方案1】:

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

Alloc::rebind&lt;T&gt;::other 如果存在,否则Alloc&lt;T, Args&gt; 如果此AllocAlloc&lt;U, Args&gt;

得到你需要的东西:

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

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

然后使用NodeAlloc 获取您的nodes。这样,如果用户没有指定分配器,您将获得默认的std::allocator&lt;T&gt;,然后使用std::allocator&lt;node&gt;。这正是你想要的,无需暴露node

【讨论】:

  • 这不正是标准库的工作原理吗?
【解决方案2】:

我需要嵌套节点,因为它需要访问 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 解决方案,尽管它似乎是针对我的具体问题量身定制的。
猜你喜欢
  • 2013-12-11
  • 1970-01-01
  • 2011-04-15
  • 1970-01-01
  • 2018-11-26
  • 2018-09-07
  • 1970-01-01
  • 2017-07-03
  • 1970-01-01
相关资源
最近更新 更多