2013-03-11 3 views
0

У меня есть ploblem о круглых шаблон ссылки. Я хочу создать дерево, используя класс node и class edge, как показано ниже;Циркуляр шаблон ссылка структура

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

+0

«edge» и «node» class должны быть базовые классы. Я планирую их повторно использовать. ex унаследованный край может содержать «поток» «reverse_flow» .... или унаследованный класс «node» может иметь больше данных, таких как флаг, ..etc ... поэтому поэтому я делаю их как шаблоны – MooMoo

+0

это не для меня какой-то смысл ... как узел может удерживать ребро с источником и местом назначения? Разве источник не всегда является самим узлом? Он должен содержать список узлов ... – Mehrdad

ответ

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++ - это функциональный язык. Существуют различные методы функционального программирования для описания рекурсивных структур без прямого объявления, которое может быть использовано.

Я держу пари, что какой-то комбинатор с фиксированной точкой может работать, но я не могу понять, как это сделать. :)