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