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

Pointer to template class as that class parameter

本文关键字:指针 参数      更新时间:2023-10-16

基本上,当试图通过邻接列表实现图时,我在定义图节点时遇到了困难:

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++模板大师们的问题是:在这种情况下使用了什么技术?

谢谢。

精确分配器并不需要精确分配器的用途。例如,在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版本)将在list内作为typedef进行提取。

编辑:允许容器规范。

这很棘手,因为不幸的是,分配器只在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>

演示。

如果EdgeLink将位于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;
};