基本上在尝试通过邻接列表实现图形时,我很难定义图形节点:
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 ++模板专家的问题是:在这种情况下使用了什么技术?
感谢。
答案 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
,您仍应该这样做,因为分配器类型reference
和pointer
(以及它们的const版本)将会在typedef
内被list
拉。
编辑:允许容器规范。
这很棘手,因为遗憾的是,只有在GraphNode
之内才定义分配器,因此您只需要在类中传递给容器,因此不能在模板外使用它。
这意味着使用模板模板参数,因此我们需要“修复”arity。由于vector
和list
只有两个参数,我们很幸运,但它可能并不总是... ...幸运的是,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>
答案 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;
};