指向模板类的指针作为该类参数

Bor*_*rzh 3 c++ templates

基本上在尝试通过邻接列表实现图形时,我很难定义图形节点:

template <
    typename Vertex, 
    typename Edge,
    typename EdgeLink = std::pair< Edge, GraphNode* >,
    typename Alloc = std::allocator< EdgeLink >
>
class GraphNode
{
public:
    Vertex vertex;
    std::list< EdgeLink, Alloc > neighbours;
};
Run Code Online (Sandbox Code Playgroud)

我意识到我不能给GraphNode模板指针赋予参数,因为它们还没有定义.我对c ++模板大师的问题是:在这种情况下使用了什么技术?

谢谢.

Mat*_* M. 6

精确分配器并不需要精确分配器可以用于什么.例如,在std::list<T>传递的分配器中std::allocator<T>然后list将分配_ListNode<T>(实现定义).这是因为分配器需要提供一种rebind机制.

template <
    typename Vertex, 
    typename Edge,
    typename Allocator = std::allocator<void*>
>
class GraphNode
{
public:
    typedef GraphNode<Vertex, Edge, Allocator> NodeType;
    typedef std::pair< Edge, NodeType* > LinkType;
    typedef typename Allocator::template rebind<LinkType>::other AllocatorType;

    Vertex vertex;
    std::list< LinkType, AllocatorType > neighbours;
};
Run Code Online (Sandbox Code Playgroud)

ideone行动.

请注意,即使它list会自己做rebind,你仍然应该这样做,因为分配器类型referencepointer(和它们的const版本)将被拉入typedef内部list.

编辑:允许容器规范.

这很棘手,因为遗憾的是,只有在你进入内部时才定义分配器GraphNode,因此你只需要在类中将它传递给容器,因此不能在模板外部使用它.

这意味着使用模板模板参数,因此我们需要"修复"arity.由于双方vectorlist只与C++ 11允许模板别名需要两个参数,我们这儿很幸运,但它可能并不总是持有......幸运的是,它不会对用户过于苛刻的要求.

template <
    typename Vertex, 
    typename Edge,
    template <typename, typename> class Container = std::vector,
    typename Allocator = std::allocator<void*>
>
class GraphNode
{
public:
    typedef GraphNode<Vertex, Edge, Container, Allocator> NodeType;
    typedef std::pair< Edge, NodeType* > LinkType;
    typedef typename Allocator::template rebind<LinkType>::other AllocatorType;
    typedef Container<LinkType, AllocatorType> NeighboursType;

    Vertex vertex;
    NeighboursType neighbours;
};
Run Code Online (Sandbox Code Playgroud)

这可以调用:

GraphNode<std::string, int>
GraphNode<std::string, int, std::list>
GraphNode<std::string, int, std::vector>
Run Code Online (Sandbox Code Playgroud)

演示.