diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 8c57e1da1..869999cb7 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -21,10 +21,6 @@ #include #include -#include -#include -#include -#include #include #include #include @@ -35,6 +31,49 @@ namespace boost { +namespace graphml_detail +{ + // The fixed list of value types GraphML understands + template < typename... Ts > struct value_type_list {}; + + template < typename List > struct for_each_value_type_impl; + + template < typename... Ts > + struct for_each_value_type_impl< value_type_list< Ts... > > + { + // f can accumulate state (type_found) + template < typename F > static void apply(F& f) + { + // an array of 0 but with the side effect of calling the functor on each type + const int expand[] = { 0, (f(Ts()), 0)... }; + (void)expand; + } + }; + + // Calls f once for each type in List, in order + template < typename List, typename F > + void for_each_value_type(F f) + { + for_each_value_type_impl< List >::apply(f); + } + + // ::value is the position of T in List. + template < typename List, typename T > + struct index_of_value_type; + + template < typename T, typename... Rest > + struct index_of_value_type< value_type_list< T, Rest... >, T > + { + static const int value = 0; + }; + + template < typename T, typename Head, typename... Rest > + struct index_of_value_type< value_type_list< Head, Rest... >, T > + { + static const int value = 1 + index_of_value_type< value_type_list< Rest... >, T >::value; + }; +} // namespace graphml_detail + ///////////////////////////////////////////////////////////////////////////// // Graph reader exceptions ///////////////////////////////////////////////////////////////////////////// @@ -111,7 +150,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph bool type_found = false; try { - mpl::for_each< value_types >( + graphml_detail::for_each_value_type< value_types >( put_property< MutableGraph*, value_types >(name, m_dp, &m_g, value, value_type, m_type_names, type_found)); } @@ -133,7 +172,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph bool type_found = false; try { - mpl::for_each< value_types >( + graphml_detail::for_each_value_type< value_types >( put_property< vertex_descriptor, value_types >(name, m_dp, any_cast< vertex_descriptor >(vertex), value, value_type, m_type_names, type_found)); @@ -156,7 +195,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph bool type_found = false; try { - mpl::for_each< value_types >( + graphml_detail::for_each_value_type< value_types >( put_property< edge_descriptor, value_types >(name, m_dp, any_cast< edge_descriptor >(edge), value, value_type, m_type_names, type_found)); @@ -192,8 +231,8 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph template < class Value > void operator()(Value) { if (m_value_type - == m_type_names[mpl::find< ValueVector, - Value >::type::pos::value]) + == m_type_names[graphml_detail::index_of_value_type< + ValueVector, Value >::value]) { put(m_name, m_dp, m_key, lexical_cast< Value >(m_value)); m_type_found = true; @@ -213,8 +252,7 @@ template < typename MutableGraph > class mutate_graph_impl : public mutate_graph protected: MutableGraph& m_g; dynamic_properties& m_dp; - typedef mpl::vector< bool, int, long, float, double, std::string > - value_types; + using value_types = graphml_detail::value_type_list< bool, int, long, float, double, std::string >; static const char* m_type_names[]; }; @@ -244,8 +282,8 @@ template < typename Types > class get_type_name template < typename Type > void operator()(Type) { if (typeid(Type) == m_type) - m_type_name - = m_type_names[mpl::find< Types, Type >::type::pos::value]; + m_type_name = m_type_names[graphml_detail::index_of_value_type< + Types, Type >::value]; } private: @@ -275,10 +313,9 @@ void write_graphml(std::ostream& out, const Graph& g, "xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns " "http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n"; - typedef mpl::vector< bool, short, unsigned short, int, unsigned int, long, - unsigned long, long long, unsigned long long, float, double, - long double, std::string > - value_types; + using value_types = graphml_detail::value_type_list< bool, short, + unsigned short, int, unsigned int, long, unsigned long, long long, + unsigned long long, float, double, long double, std::string >; const char* type_names[] = { "boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string" }; std::map< std::string, std::string > graph_key_ids; @@ -299,8 +336,9 @@ void write_graphml(std::ostream& out, const Graph& g, else continue; std::string type_name = "string"; - mpl::for_each< value_types >(get_type_name< value_types >( - i->second->value(), type_names, type_name)); + graphml_detail::for_each_value_type< value_types >( + get_type_name< value_types >( + i->second->value(), type_names, type_name)); out << " second->key() == typeid(Graph*) ? "graph"