graph_traits.hpp 13 KB

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