graph_traits.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. //=======================================================================
  2. // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
  3. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //=======================================================================
  9. #ifndef BOOST_GRAPH_TRAITS_HPP
  10. #define BOOST_GRAPH_TRAITS_HPP
  11. #include <boost/config.hpp>
  12. #include <iterator>
  13. #include <utility> /* Primarily for std::pair */
  14. #include <boost/tuple/tuple.hpp>
  15. #include <boost/mpl/if.hpp>
  16. #include <boost/mpl/eval_if.hpp>
  17. #include <boost/mpl/bool.hpp>
  18. #include <boost/mpl/not.hpp>
  19. #include <boost/mpl/has_xxx.hpp>
  20. #include <boost/mpl/void.hpp>
  21. #include <boost/mpl/identity.hpp>
  22. #include <boost/type_traits/is_same.hpp>
  23. #include <boost/iterator/iterator_categories.hpp>
  24. #include <boost/iterator/iterator_adaptor.hpp>
  25. #include <boost/pending/property.hpp>
  26. #include <boost/detail/workaround.hpp>
  27. namespace boost {
  28. namespace detail {
  29. #define BOOST_GRAPH_MEMBER_OR_VOID(name) \
  30. BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
  31. template <typename T> struct BOOST_JOIN(get_member_, name) {typedef typename T::name type;}; \
  32. template <typename T> struct BOOST_JOIN(get_opt_member_, name): \
  33. boost::mpl::eval_if_c< \
  34. BOOST_JOIN(has_, name)<T>::value, \
  35. BOOST_JOIN(get_member_, name)<T>, \
  36. boost::mpl::identity<void> > \
  37. {};
  38. BOOST_GRAPH_MEMBER_OR_VOID(adjacency_iterator)
  39. BOOST_GRAPH_MEMBER_OR_VOID(out_edge_iterator)
  40. BOOST_GRAPH_MEMBER_OR_VOID(in_edge_iterator)
  41. BOOST_GRAPH_MEMBER_OR_VOID(vertex_iterator)
  42. BOOST_GRAPH_MEMBER_OR_VOID(edge_iterator)
  43. BOOST_GRAPH_MEMBER_OR_VOID(vertices_size_type)
  44. BOOST_GRAPH_MEMBER_OR_VOID(edges_size_type)
  45. BOOST_GRAPH_MEMBER_OR_VOID(degree_size_type)
  46. }
  47. template <typename G>
  48. struct graph_traits {
  49. #define BOOST_GRAPH_PULL_OPT_MEMBER(name) \
  50. typedef typename detail::BOOST_JOIN(get_opt_member_, name)<G>::type name;
  51. typedef typename G::vertex_descriptor vertex_descriptor;
  52. typedef typename G::edge_descriptor edge_descriptor;
  53. BOOST_GRAPH_PULL_OPT_MEMBER(adjacency_iterator)
  54. BOOST_GRAPH_PULL_OPT_MEMBER(out_edge_iterator)
  55. BOOST_GRAPH_PULL_OPT_MEMBER(in_edge_iterator)
  56. BOOST_GRAPH_PULL_OPT_MEMBER(vertex_iterator)
  57. BOOST_GRAPH_PULL_OPT_MEMBER(edge_iterator)
  58. typedef typename G::directed_category directed_category;
  59. typedef typename G::edge_parallel_category edge_parallel_category;
  60. typedef typename G::traversal_category traversal_category;
  61. BOOST_GRAPH_PULL_OPT_MEMBER(vertices_size_type)
  62. BOOST_GRAPH_PULL_OPT_MEMBER(edges_size_type)
  63. BOOST_GRAPH_PULL_OPT_MEMBER(degree_size_type)
  64. #undef BOOST_GRAPH_PULL_OPT_MEMBER
  65. static inline vertex_descriptor null_vertex();
  66. };
  67. template <typename G>
  68. inline typename graph_traits<G>::vertex_descriptor
  69. graph_traits<G>::null_vertex()
  70. { return G::null_vertex(); }
  71. // directed_category tags
  72. struct directed_tag { };
  73. struct undirected_tag { };
  74. struct bidirectional_tag : public directed_tag { };
  75. namespace detail {
  76. inline bool is_directed(directed_tag) { return true; }
  77. inline bool is_directed(undirected_tag) { return false; }
  78. }
  79. /** Return true if the given graph is directed. */
  80. template <typename Graph>
  81. bool is_directed(const Graph&) {
  82. typedef typename graph_traits<Graph>::directed_category Cat;
  83. return detail::is_directed(Cat());
  84. }
  85. /** Return true if the given graph is undirected. */
  86. template <typename Graph>
  87. bool is_undirected(const Graph& g) {
  88. return !is_directed(g);
  89. }
  90. /** @name Directed/Undirected Graph Traits */
  91. //@{
  92. namespace graph_detail {
  93. template <typename Tag>
  94. struct is_directed_tag
  95. : mpl::bool_<is_convertible<Tag, directed_tag>::value>
  96. { };
  97. } // namespace graph_detail
  98. template <typename Graph>
  99. struct is_directed_graph
  100. : graph_detail::is_directed_tag<
  101. typename graph_traits<Graph>::directed_category
  102. >
  103. { };
  104. template <typename Graph>
  105. struct is_undirected_graph
  106. : mpl::not_< is_directed_graph<Graph> >
  107. { };
  108. //@}
  109. // edge_parallel_category tags
  110. struct allow_parallel_edge_tag { };
  111. struct disallow_parallel_edge_tag { };
  112. namespace detail {
  113. inline bool allows_parallel(allow_parallel_edge_tag) { return true; }
  114. inline bool allows_parallel(disallow_parallel_edge_tag) { return false; }
  115. }
  116. template <typename Graph>
  117. bool allows_parallel_edges(const Graph&) {
  118. typedef typename graph_traits<Graph>::edge_parallel_category Cat;
  119. return detail::allows_parallel(Cat());
  120. }
  121. /** @name Parallel Edges Traits */
  122. //@{
  123. /**
  124. * The is_multigraph metafunction returns true if the graph allows
  125. * parallel edges. Technically, a multigraph is a simple graph that
  126. * allows parallel edges, but since there are no traits for the allowance
  127. * or disallowance of loops, this is a moot point.
  128. */
  129. template <typename Graph>
  130. struct is_multigraph
  131. : mpl::bool_<
  132. is_same<
  133. typename graph_traits<Graph>::edge_parallel_category,
  134. allow_parallel_edge_tag
  135. >::value
  136. >
  137. { };
  138. //@}
  139. // traversal_category tags
  140. struct incidence_graph_tag { };
  141. struct adjacency_graph_tag { };
  142. struct bidirectional_graph_tag : virtual incidence_graph_tag { };
  143. struct vertex_list_graph_tag { };
  144. struct edge_list_graph_tag { };
  145. struct adjacency_matrix_tag { };
  146. // Parallel traversal_category tags
  147. struct distributed_graph_tag { };
  148. struct distributed_vertex_list_graph_tag { };
  149. struct distributed_edge_list_graph_tag { };
  150. #define BOOST_GRAPH_SEQUENTIAL_TRAITS_DEFINES_DISTRIBUTED_TAGS // Disable these from external versions of PBGL
  151. /** @name Traversal Category Traits
  152. * These traits classify graph types by their supported methods of
  153. * vertex and edge traversal.
  154. */
  155. //@{
  156. template <typename Graph>
  157. struct is_incidence_graph
  158. : mpl::bool_<
  159. is_convertible<
  160. typename graph_traits<Graph>::traversal_category,
  161. incidence_graph_tag
  162. >::value
  163. >
  164. { };
  165. template <typename Graph>
  166. struct is_bidirectional_graph
  167. : mpl::bool_<
  168. is_convertible<
  169. typename graph_traits<Graph>::traversal_category,
  170. bidirectional_graph_tag
  171. >::value
  172. >
  173. { };
  174. template <typename Graph>
  175. struct is_vertex_list_graph
  176. : mpl::bool_<
  177. is_convertible<
  178. typename graph_traits<Graph>::traversal_category,
  179. vertex_list_graph_tag
  180. >::value
  181. >
  182. { };
  183. template <typename Graph>
  184. struct is_edge_list_graph
  185. : mpl::bool_<
  186. is_convertible<
  187. typename graph_traits<Graph>::traversal_category,
  188. edge_list_graph_tag
  189. >::value
  190. >
  191. { };
  192. template <typename Graph>
  193. struct is_adjacency_matrix
  194. : mpl::bool_<
  195. is_convertible<
  196. typename graph_traits<Graph>::traversal_category,
  197. adjacency_matrix_tag
  198. >::value
  199. >
  200. { };
  201. //@}
  202. /** @name Directed Graph Traits
  203. * These metafunctions are used to fully classify directed vs. undirected
  204. * graphs. Recall that an undirected graph is also bidirectional, but it
  205. * cannot be both undirected and directed at the same time.
  206. */
  207. //@{
  208. template <typename Graph>
  209. struct is_directed_unidirectional_graph
  210. : mpl::and_<
  211. is_directed_graph<Graph>, mpl::not_< is_bidirectional_graph<Graph> >
  212. >
  213. { };
  214. template <typename Graph>
  215. struct is_directed_bidirectional_graph
  216. : mpl::and_<
  217. is_directed_graph<Graph>, is_bidirectional_graph<Graph>
  218. >
  219. { };
  220. //@}
  221. //?? not the right place ?? Lee
  222. typedef boost::forward_traversal_tag multi_pass_input_iterator_tag;
  223. namespace detail {
  224. BOOST_MPL_HAS_XXX_TRAIT_DEF(graph_property_type)
  225. BOOST_MPL_HAS_XXX_TRAIT_DEF(edge_property_type)
  226. BOOST_MPL_HAS_XXX_TRAIT_DEF(vertex_property_type)
  227. template <typename G> struct get_graph_property_type {typedef typename G::graph_property_type type;};
  228. template <typename G> struct get_edge_property_type {typedef typename G::edge_property_type type;};
  229. template <typename G> struct get_vertex_property_type {typedef typename G::vertex_property_type type;};
  230. }
  231. template <typename G>
  232. struct graph_property_type
  233. : boost::mpl::eval_if<detail::has_graph_property_type<G>,
  234. detail::get_graph_property_type<G>,
  235. no_property> {};
  236. template <typename G>
  237. struct edge_property_type
  238. : boost::mpl::eval_if<detail::has_edge_property_type<G>,
  239. detail::get_edge_property_type<G>,
  240. no_property> {};
  241. template <typename G>
  242. struct vertex_property_type
  243. : boost::mpl::eval_if<detail::has_vertex_property_type<G>,
  244. detail::get_vertex_property_type<G>,
  245. no_property> {};
  246. template<typename G>
  247. struct graph_bundle_type {
  248. typedef typename G::graph_bundled type;
  249. };
  250. template<typename G>
  251. struct vertex_bundle_type {
  252. typedef typename G::vertex_bundled type;
  253. };
  254. template<typename G>
  255. struct edge_bundle_type {
  256. typedef typename G::edge_bundled type;
  257. };
  258. namespace graph { namespace detail {
  259. template<typename Graph, typename Descriptor>
  260. class bundled_result {
  261. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  262. typedef typename mpl::if_c<(is_same<Descriptor, Vertex>::value),
  263. vertex_bundle_type<Graph>,
  264. edge_bundle_type<Graph> >::type bundler;
  265. public:
  266. typedef typename bundler::type type;
  267. };
  268. template<typename Graph>
  269. class bundled_result<Graph, graph_bundle_t> {
  270. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  271. typedef graph_bundle_type<Graph> bundler;
  272. public:
  273. typedef typename bundler::type type;
  274. };
  275. } } // namespace graph::detail
  276. namespace graph_detail {
  277. // A helper metafunction for determining whether or not a type is
  278. // bundled.
  279. template <typename T>
  280. struct is_no_bundle : mpl::bool_<is_same<T, no_property>::value>
  281. { };
  282. } // namespace graph_detail
  283. /** @name Graph Property Traits
  284. * These metafunctions (along with those above), can be used to access the
  285. * vertex and edge properties (bundled or otherwise) of vertices and
  286. * edges.
  287. */
  288. //@{
  289. template<typename Graph>
  290. struct has_graph_property
  291. : mpl::not_<
  292. typename detail::is_no_property<
  293. typename graph_property_type<Graph>::type
  294. >::type
  295. >::type
  296. { };
  297. template<typename Graph>
  298. struct has_bundled_graph_property
  299. : mpl::not_<
  300. graph_detail::is_no_bundle<typename graph_bundle_type<Graph>::type>
  301. >
  302. { };
  303. template <typename Graph>
  304. struct has_vertex_property
  305. : mpl::not_<
  306. typename detail::is_no_property<typename vertex_property_type<Graph>::type>
  307. >::type
  308. { };
  309. template <typename Graph>
  310. struct has_bundled_vertex_property
  311. : mpl::not_<
  312. graph_detail::is_no_bundle<typename vertex_bundle_type<Graph>::type>
  313. >
  314. { };
  315. template <typename Graph>
  316. struct has_edge_property
  317. : mpl::not_<
  318. typename detail::is_no_property<typename edge_property_type<Graph>::type>
  319. >::type
  320. { };
  321. template <typename Graph>
  322. struct has_bundled_edge_property
  323. : mpl::not_<
  324. graph_detail::is_no_bundle<typename edge_bundle_type<Graph>::type>
  325. >
  326. { };
  327. //@}
  328. } // namespace boost
  329. // Since pair is in namespace std, Koenig lookup will find source and
  330. // target if they are also defined in namespace std. This is illegal,
  331. // but the alternative is to put source and target in the global
  332. // namespace which causes name conflicts with other libraries (like
  333. // SUIF).
  334. namespace std {
  335. /* Some helper functions for dealing with pairs as edges */
  336. template <class T, class G>
  337. T source(pair<T,T> p, const G&) { return p.first; }
  338. template <class T, class G>
  339. T target(pair<T,T> p, const G&) { return p.second; }
  340. }
  341. #if defined(__GNUC__) && defined(__SGI_STL_PORT)
  342. // For some reason g++ with STLport does not see the above definition
  343. // of source() and target() unless we bring them into the boost
  344. // namespace.
  345. namespace boost {
  346. using std::source;
  347. using std::target;
  348. }
  349. #endif
  350. #endif // BOOST_GRAPH_TRAITS_HPP