|
Boost : |
From: Ares Lagae (ares.lagae_at_[hidden])
Date: 2008-03-13 05:15:25
I discovered an interesting pattern that makes it easy to customize elements
in complex data structures. For example, customizing nodes and edges of a
graph, or vertices edges and faces of a mesh. I found it interesting and
wanted to share it. I have attached an example involving graphs, although I
currently use it to customize 3D meshes. Maybe it is of interest to anyone.
I am open for comments and suggestions.
-- Ares Lagae Computer Graphics Research Group, Katholieke Universiteit Leuven http://www.cs.kuleuven.be/~ares/ // ----------------------------------------------------------------------------- // general node, edge, graph #include <vector> template <typename GraphType> class node { public: node() {} }; template <typename GraphType> class edge { public: typedef GraphType graph_type; typedef typename graph_type::node_iterator node_iterator; edge() {} edge(node_iterator node_0, node_iterator node_1) { nodes_[0] = node_0; nodes_[1] = node_1; } private: node_iterator nodes_[2]; }; template < template <typename> class NodeType, template <typename> class EdgeType > class graph { public: typedef graph graph_type; typedef node<graph_type> node_base_type; typedef edge<graph_type> edge_base_type; typedef NodeType<graph_type> node_type; typedef EdgeType<graph_type> edge_type; typedef typename std::vector<node_type>::iterator node_iterator; typedef typename std::vector<edge_type>::iterator edge_iterator; node_iterator insert(const node_type& node) { return nodes_.insert(nodes_.end(), node); } edge_iterator insert(const edge_type& edge) { return edges_.insert(edges_.end(), edge); } private: std::vector<node_type> nodes_; std::vector<edge_type> edges_; }; // ----------------------------------------------------------------------------- // custom my_node, my_edge template <typename GraphType> class my_node : public GraphType::node_base_type { public: typedef GraphType graph_type; typedef typename graph_type::node_base_type node_base_type; my_node() : node_base_type() {} // custom members }; template <typename GraphType> class my_edge : public GraphType::edge_base_type { public: typedef GraphType graph_type; typedef typename graph_type::edge_base_type edge_base_type; typedef typename graph_type::node_iterator node_iterator; my_edge() : edge_base_type() {} my_edge(node_iterator node_0, node_iterator node_1) : edge_base_type(node_0, node_1) {} // custom members }; // ----------------------------------------------------------------------------- // main int main(int argc, char* argv[]) { { // graph using node and edge typedef graph<node, edge> graph_type; graph_type g; graph_type::node_iterator ni1 = g.insert(graph_type::node_type()); graph_type::node_iterator ni2 = g.insert(graph_type::node_type()); graph_type::edge_iterator ei = g.insert(graph_type::edge_type(ni1, ni2)); } { // graph using my_node and edge typedef graph<my_node, edge> graph_type; graph_type g; graph_type::node_iterator ni1 = g.insert(graph_type::node_type()); graph_type::node_iterator ni2 = g.insert(graph_type::node_type()); graph_type::edge_iterator ei = g.insert(graph_type::edge_type(ni1, ni2)); } { // graph using my_node and my_edge typedef graph<my_node, my_edge> graph_type; graph_type g; graph_type::node_iterator ni1 = g.insert(graph_type::node_type()); graph_type::node_iterator ni2 = g.insert(graph_type::node_type()); graph_type::edge_iterator ei = g.insert(graph_type::edge_type(ni1, ni2)); } { // graph using node and my_edge typedef graph<node, my_edge> graph_type; graph_type g; graph_type::node_iterator ni1 = g.insert(graph_type::node_type()); graph_type::node_iterator ni2 = g.insert(graph_type::node_type()); graph_type::edge_iterator ei = g.insert(graph_type::edge_type(ni1, ni2)); } }
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk