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

时间:2012-02-21 16:00:38

标签: 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;
};

我意识到我无法为GraphNode模板指针提供参数,因为它们尚未定义。我对c ++模板专家的问题是:在这种情况下使用了什么技术?

感谢。

2 个答案:

答案 0 :(得分: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;
};

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;
};

可以这样调用:

GraphNode<std::string, int>
GraphNode<std::string, int, std::list>
GraphNode<std::string, int, std::vector>

Demo

答案 1 :(得分:1)

如果您的EdgeLink将在&#39;内部&#39;对于GraphNode,最好不要将其声明为模板参数。而是使用这种方法:

template <
    typename Vertex, 
    typename Edge
>
class GraphNode
{
public:
    typedef GraphNode<Vertex, Edge> NodeType;
    typedef std::pair< Edge, NodeType* > LinkType;
    typedef std::allocator< Linktype > AllocType;
    Vertex vertex;
    std::list< LinkType, AllocType > neighbours;
};