2013-03-11 81 views
0

我有一个关于圆形模板参考的构造。我想用类节点和类边做一棵树,如下所示:圆形模板参考结构

template <typename EdgeT> 
class node 
{ 
public: 
    std::vector<EdgeT> edge_out; 
    std::vector<EdgeT> edge_in; 
}; 


template <typename NodeT> 
class edge 
{ 
public: 
    NodeT* src; 
    NodeT* dst; 
    int weight; 
}; 


template <typename NodeT, typename EdgeT> 
class graph 
{ 
public: 
    std::vector<NodeT> nodes; 
}; 

我发现我不能宣布图形类ex:

graph< node, edge > g; // <--- this cannot be solved 

graph< node< edge <node.....>, edge< node< edge>> > //it makes infinity declaration.. 

我如何重新定义类的结构?

+0

它是否必须模板化? – Xymostech 2013-03-11 01:59:48

+0

“边缘”和“节点”类应该有基类。我打算重用它们。如果继承的边缘可以包含“flow”“reverse_flow”....或者继承的“节点”类可以包含更多数据,例如flag,..etc ...这就是为什么我将它们作为模板 – MooMoo 2013-03-11 02:05:34

+0

这不是对我来说有意义......一个节点如何能够拥有源和目的地的边缘?源不是始终是节点本身吗?它应该有一个节点列表... – Mehrdad 2013-03-11 02:57:44

回答

0

你需要弄清楚为什么你需要使用模板。例如,如果你想在一个边缘的动态数据,你可以使用:

//foward declaration 
template <typename T> 
class node 
{ 
std::vector<Edge<T> > edge_out; 
std::vector<Edge<T> > edge_in; 
} 


template <typename T> 
class edge 
{ 
Node<T>* src; 
Node<T>* dst; 
T weight 
} 


template <typename T> 
class graph 
{ 
std::vector<Node<T> > nodes; 
} 

同样的,如果你想有一个在你的节点不同的数据。但总的来说,最好事先弄清楚模板的原因。我看了过度的模板化生产代码,这是很难维护的。

2

这里有一个办法:

#include <vector> 

template<template<typename NodeT,typename T>class EdgeT, typename T=double> 
struct Node { 
    typedef Node<EdgeT,T> self_type; 
    typedef EdgeT<self_type, T> edge_type; 
    std::vector<edge_type> edge_out; 
    std::vector<edge_type> edge_in; 
    T data; 
}; 

template<typename NodeT,typename T> 
struct Edge { 
    typedef NodeT node_type; 
    node_type* src; 
    node_type* dst; 
    int weight; 
}; 

template<typename NodeT, typename EdgeT=typename NodeT::edge_type> 
struct graph { 
    typedef NodeT node_type; 
    typedef EdgeT edge_type; 
    std::vector<NodeT> nodes; 
}; 

int main() { 
    typedef graph< Node<Edge> > graph_type; 
    graph_type my_graph; 
    my_graph.nodes.push_back(graph_type::node_type()); 
    my_graph.nodes.push_back(graph_type::node_type()); 
    my_graph.nodes.front().edge_out.push_back({&my_graph.nodes[0], &my_graph.nodes[1], 1}); 
    my_graph.nodes.back().edge_in.push_back({&my_graph.nodes[0], &my_graph.nodes[1], 1}); 
} 

的另一种方法,你可以看看如何处理boost::variant递归变种。

解决这个问题的另一种方法是更正式的。 C++模板元编程是一种功能性语言 - 函数式编程中有各种技术来描述递归结构,而无需使用前向声明。

我敢打赌,某种固定点的combinator可能会起作用,但我无法想象如何。 :)