3
template <class Data, class Allocator = std::allocator<Node> >
class Node : public Data {
  // ...
};

问题很简单,如何让上面的代码编译?目的是让 Node 有可能分配其他节点(并提供默认分配器)。

4

5 回答 5

6

不能这样写:

template <class Data, class Allocator>
class Node;

template <class Data, class Allocator = 
  std::allocator<Node<Data, std::allocator<Node<...> >
class Node : public Data {
  // ...
};

因为默认参数将不得不重复。不过,您可以使用标签类型

struct DefaultAllocatorTag { };

template<typename Alloc, typename Node>
struct SelectAllocator {
  typedef Alloc type;
};

template<typename Node>
struct SelectAllocator<DefaultAllocatorTag, Node> {
  typedef std::allocator<Node> type;
};

template <class Data, class Allocator = DefaultAllocatorTag >
class Node : public Data {
  typedef typename SelectAllocator<Allocator, Node>::type 
    NodeAllocator;
};

不过,如果适用,我会确定容器中的分配器。像这样:

template<typename Data, typename Allocator = std::allocator<Data> >
struct Container {
  struct Node : Data { 
    typedef typename Allocator::template rebind<Node>::other NodeAllocator;
    ...
  };
  ...
};
于 2009-09-21T20:45:26.080 回答
6

最后我解决了!解决方案是将默认分配器的特化延迟到已经定义了 Node 的类内部:

template <class Data, template<class T> class TAllocator = std::allocator >
class Node : public Data {
  typedef TAllocator<Node> Allocator;
  // ...
};
于 2009-09-21T21:35:25.023 回答
2

这个怎么样?:

#include <memory>

template<class Data>
class NodeImpl : public Data
{
};

template<class Data, class Allocator = std::allocator< NodeImpl<Data> > >
class Node : public NodeImpl<Data>
{
};

class MyAllocator
{
};

class MyDataClass
{
};

int main()
{
    Node<MyDataClass> node;

    Node<MyDataClass, MyAllocator> node_with_alloc;

    return 0;
}
于 2009-09-21T20:52:17.717 回答
1

你不能让它编译——你试图创建的是一个“无限”类型。

让我们从那开始,你不能使用未实例化的类模板作为模板参数。因此,您需要将 Node 传递给 std::allocator,如下所示:

template <class Data, class Allocator = std::allocator<Node<Data, Something> > > 
class Node ...

然而,那会是什么?好吧,std::allocator

诀窍是分配器不仅需要分配它们的模板参数,还需要分配任何其他类型。宣布你的班级为

template <class Data, class Allocator = std::allocator<Data> > class Node ...

然后,为这样的节点创建分配器:

typename Allocator::rebind<Node>::other nodeAllocator(myDataAllocator)

这篇关于分配器的 vcblog 文章可能会有所帮助,尽管它过于关注迭代器。

于 2009-09-21T20:53:59.210 回答
0

另一种解决方案。这个好像比较典型。IE。矢量和智能指针实现使用类似的东西。这个想法是从分配器私下继承:

template <class Data, template <class N> class Allocator = std::allocator>
class Node : public Data, private Allocator<Node<Data, Allocator> > {
  // ...
};

好处是在继承声明中我们已经可以使用 Node.js 了。

于 2009-09-22T11:46:17.690 回答