1 //=======================================================================
2 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
3 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
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 //=======================================================================
10 #ifndef BOOST_GRAPH_ADJACENCY_LIST_HPP
11 #define BOOST_GRAPH_ADJACENCY_LIST_HPP
14 #include <boost/config.hpp>
20 #if !defined BOOST_NO_HASH
21 # ifdef BOOST_HASH_SET_HEADER
22 # include BOOST_HASH_SET_HEADER
28 #if !defined BOOST_NO_SLIST
29 # ifdef BOOST_SLIST_HEADER
30 # include BOOST_SLIST_HEADER
36 #include <boost/graph/graph_traits.hpp>
37 #include <boost/graph/graph_selectors.hpp>
38 #include <boost/property_map.hpp>
39 #include <boost/pending/ct_if.hpp>
40 #include <boost/graph/detail/edge.hpp>
41 #include <boost/type_traits/is_same.hpp>
42 #include <boost/detail/workaround.hpp>
43 #include <boost/graph/properties.hpp>
47 //===========================================================================
48 // Selectors for the VertexList and EdgeList template parameters of
49 // adjacency_list, and the container_gen traits class which is used
50 // to map the selectors to the container type used to implement the
53 // The main container_gen traits class uses partial specialization,
54 // so we also include a workaround.
56 #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
58 #if !defined BOOST_NO_SLIST
67 #if !defined BOOST_NO_HASH
72 template <class Selector, class ValueType>
73 struct container_gen { };
75 template <class ValueType>
76 struct container_gen<listS, ValueType> {
77 typedef std::list<ValueType> type;
79 #if !defined BOOST_NO_SLIST
80 template <class ValueType>
81 struct container_gen<slistS, ValueType> {
82 typedef BOOST_STD_EXTENSION_NAMESPACE::slist<ValueType> type;
85 template <class ValueType>
86 struct container_gen<vecS, ValueType> {
87 typedef std::vector<ValueType> type;
90 template <class ValueType>
91 struct container_gen<mapS, ValueType> {
92 typedef std::set<ValueType> type;
95 template <class ValueType>
96 struct container_gen<setS, ValueType> {
97 typedef std::set<ValueType> type;
100 template <class ValueType>
101 struct container_gen<multisetS, ValueType> {
102 typedef std::multiset<ValueType> type;
105 #if !defined BOOST_NO_HASH
106 template <class ValueType>
107 struct container_gen<hash_mapS, ValueType> {
108 typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<ValueType> type;
111 template <class ValueType>
112 struct container_gen<hash_setS, ValueType> {
113 typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<ValueType> type;
117 #else // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
119 #if !defined BOOST_NO_SLIST
122 struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::slist<T> type; };
128 struct bind_ { typedef std::vector<T> type; };
133 struct bind_ { typedef std::list<T> type; };
138 struct bind_ { typedef std::set<T, std::less<T> > type; };
143 struct bind_ { typedef std::multiset<T, std::less<T> > type; };
146 #if !defined BOOST_NO_HASH
149 struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<T, std::less<T> > type; };
155 struct bind_ { typedef std::set<T, std::less<T> > type; };
158 #if !defined BOOST_NO_HASH
161 struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<T, std::less<T> > type; };
165 template <class Selector> struct container_selector {
169 #define BOOST_CONTAINER_SELECTOR(NAME) \
170 template <> struct container_selector<NAME> { \
174 BOOST_CONTAINER_SELECTOR(vecS);
175 BOOST_CONTAINER_SELECTOR(listS);
176 BOOST_CONTAINER_SELECTOR(mapS);
177 BOOST_CONTAINER_SELECTOR(setS);
178 BOOST_CONTAINER_SELECTOR(multisetS);
179 #if !defined BOOST_NO_HASH
180 BOOST_CONTAINER_SELECTOR(hash_mapS);
182 #if !defined BOOST_NO_SLIST
183 BOOST_CONTAINER_SELECTOR(slistS);
186 template <class Selector, class ValueType>
187 struct container_gen {
188 typedef typename container_selector<Selector>::type Select;
189 typedef typename Select:: template bind_<ValueType>::type type;
192 #endif // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
194 template <class StorageSelector>
195 struct parallel_edge_traits { };
198 struct parallel_edge_traits<vecS> {
199 typedef allow_parallel_edge_tag type; };
202 struct parallel_edge_traits<listS> {
203 typedef allow_parallel_edge_tag type; };
205 #if !defined BOOST_NO_SLIST
207 struct parallel_edge_traits<slistS> {
208 typedef allow_parallel_edge_tag type; };
212 struct parallel_edge_traits<setS> {
213 typedef disallow_parallel_edge_tag type; };
216 struct parallel_edge_traits<multisetS> {
217 typedef allow_parallel_edge_tag type; };
219 #if !defined BOOST_NO_HASH
221 struct parallel_edge_traits<hash_setS> {
222 typedef disallow_parallel_edge_tag type;
226 // mapS is obsolete, replaced with setS
228 struct parallel_edge_traits<mapS> {
229 typedef disallow_parallel_edge_tag type; };
231 #if !defined BOOST_NO_HASH
233 struct parallel_edge_traits<hash_mapS> {
234 typedef disallow_parallel_edge_tag type;
239 template <class Directed> struct is_random_access {
240 enum { value = false};
241 typedef false_type type;
244 struct is_random_access<vecS> {
245 enum { value = true };
246 typedef true_type type;
249 } // namespace detail
253 //===========================================================================
254 // The adjacency_list_traits class, which provides a way to access
255 // some of the associated types of an adjacency_list type without
256 // having to first create the adjacency_list type. This is useful
257 // when trying to create interior vertex or edge properties who's
258 // value type is a vertex or edge descriptor.
260 template <class OutEdgeListS = vecS,
261 class VertexListS = vecS,
262 class DirectedS = directedS>
263 struct adjacency_list_traits
265 typedef typename detail::is_random_access<VertexListS>::type
267 typedef typename DirectedS::is_bidir_t is_bidir;
268 typedef typename DirectedS::is_directed_t is_directed;
270 typedef typename boost::ct_if_t<is_bidir,
272 typename boost::ct_if_t<is_directed,
273 directed_tag, undirected_tag
275 >::type directed_category;
277 typedef typename parallel_edge_traits<OutEdgeListS>::type
278 edge_parallel_category;
280 typedef void* vertex_ptr;
281 typedef typename boost::ct_if_t<is_rand_access,
282 std::size_t, vertex_ptr>::type vertex_descriptor;
283 typedef detail::edge_desc_impl<directed_category, vertex_descriptor>
289 #include <boost/graph/detail/adjacency_list.hpp>
293 //===========================================================================
294 // The adjacency_list class.
297 template <class OutEdgeListS = vecS, // a Sequence or an AssociativeContainer
298 class VertexListS = vecS, // a Sequence or a RandomAccessContainer
299 class DirectedS = directedS,
300 class VertexProperty = no_property,
301 class EdgeProperty = no_property,
302 class GraphProperty = no_property,
303 class EdgeListS = listS>
305 : public detail::adj_list_gen<
306 adjacency_list<OutEdgeListS,VertexListS,DirectedS,
307 VertexProperty,EdgeProperty,GraphProperty,EdgeListS>,
308 VertexListS, OutEdgeListS, DirectedS,
309 #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
310 typename detail::retag_property_list<vertex_bundle_t,
311 VertexProperty>::type,
312 typename detail::retag_property_list<edge_bundle_t, EdgeProperty>::type,
314 VertexProperty, EdgeProperty,
316 GraphProperty, EdgeListS>::type
318 #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
319 typedef typename detail::retag_property_list<vertex_bundle_t,
320 VertexProperty>::retagged
321 maybe_vertex_bundled;
323 typedef typename detail::retag_property_list<edge_bundle_t,
324 EdgeProperty>::retagged
329 #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
330 typedef typename detail::retag_property_list<vertex_bundle_t,
331 VertexProperty>::type
332 vertex_property_type;
333 typedef typename detail::retag_property_list<edge_bundle_t,
337 // The types that are actually bundled
338 typedef typename ct_if<(is_same<maybe_vertex_bundled, no_property>::value),
340 maybe_vertex_bundled>::type vertex_bundled;
341 typedef typename ct_if<(is_same<maybe_edge_bundled, no_property>::value),
343 maybe_edge_bundled>::type edge_bundled;
345 typedef VertexProperty vertex_property_type;
346 typedef EdgeProperty edge_property_type;
347 typedef no_vertex_bundle vertex_bundled;
348 typedef no_edge_bundle edge_bundled;
352 typedef adjacency_list self;
353 typedef typename detail::adj_list_gen<
354 self, VertexListS, OutEdgeListS, DirectedS,
355 vertex_property_type, edge_property_type, GraphProperty, EdgeListS
359 typedef typename Base::stored_vertex stored_vertex;
360 typedef typename Base::vertices_size_type vertices_size_type;
361 typedef typename Base::edges_size_type edges_size_type;
362 typedef typename Base::degree_size_type degree_size_type;
363 typedef typename Base::vertex_descriptor vertex_descriptor;
364 typedef typename Base::edge_descriptor edge_descriptor;
365 typedef OutEdgeListS out_edge_list_selector;
366 typedef VertexListS vertex_list_selector;
367 typedef DirectedS directed_selector;
368 typedef EdgeListS edge_list_selector;
370 typedef GraphProperty graph_property_type;
372 inline adjacency_list(const GraphProperty& p = GraphProperty())
375 inline adjacency_list(const adjacency_list& x)
376 : Base(x), m_property(x.m_property) { }
378 inline adjacency_list& operator=(const adjacency_list& x) {
379 // TBD: probably should give the strong guarantee
382 m_property = x.m_property;
387 // Required by Mutable Graph
388 inline adjacency_list(vertices_size_type num_vertices,
389 const GraphProperty& p = GraphProperty())
390 : Base(num_vertices), m_property(p) { }
392 #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
393 // Required by Iterator Constructible Graph
394 template <class EdgeIterator>
395 inline adjacency_list(EdgeIterator first, EdgeIterator last,
396 vertices_size_type n,
398 const GraphProperty& p = GraphProperty())
399 : Base(n, first, last), m_property(p) { }
401 template <class EdgeIterator, class EdgePropertyIterator>
402 inline adjacency_list(EdgeIterator first, EdgeIterator last,
403 EdgePropertyIterator ep_iter,
404 vertices_size_type n,
406 const GraphProperty& p = GraphProperty())
407 : Base(n, first, last, ep_iter), m_property(p) { }
410 void swap(adjacency_list& x) {
411 // Is there a more efficient way to do this?
412 adjacency_list tmp(x);
417 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
418 // Directly access a vertex or edge bundle
419 vertex_bundled& operator[](vertex_descriptor v)
420 { return get(vertex_bundle, *this)[v]; }
422 const vertex_bundled& operator[](vertex_descriptor v) const
423 { return get(vertex_bundle, *this)[v]; }
425 edge_bundled& operator[](edge_descriptor e)
426 { return get(edge_bundle, *this)[e]; }
428 const edge_bundled& operator[](edge_descriptor e) const
429 { return get(edge_bundle, *this)[e]; }
432 // protected: (would be protected if friends were more portable)
433 GraphProperty m_property;
436 template <class OEL, class VL, class DirS, class VP,class EP, class GP,
437 class EL, class Tag, class Value>
439 set_property(adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>& g, Tag,
440 const Value& value) {
441 get_property_value(g.m_property, Tag()) = value;;
444 template <class OEL, class VL, class DirS, class VP, class EP, class GP,
447 typename graph_property<adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>, Tag>::type&
448 get_property(adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>& g, Tag) {
449 return get_property_value(g.m_property, Tag());
452 template <class OEL, class VL, class DirS, class VP, class EP, class GP,
456 typename graph_property<adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>, Tag>::type&
457 get_property(const adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>& g, Tag) {
458 return get_property_value(g.m_property, Tag());
461 // dwa 09/25/00 - needed to be more explicit so reverse_graph would work.
462 template <class Directed, class Vertex,
466 class VertexProperty,
468 class GraphProperty, class EdgeListS>
470 source(const detail::edge_base<Directed,Vertex>& e,
471 const adjacency_list<OutEdgeListS, VertexListS, DirectedS,
472 VertexProperty, EdgeProperty, GraphProperty, EdgeListS>&)
477 template <class Directed, class Vertex, class OutEdgeListS,
478 class VertexListS, class DirectedS, class VertexProperty,
479 class EdgeProperty, class GraphProperty, class EdgeListS>
481 target(const detail::edge_base<Directed,Vertex>& e,
482 const adjacency_list<OutEdgeListS, VertexListS, DirectedS,
483 VertexProperty, EdgeProperty, GraphProperty, EdgeListS>&)
488 // Support for bundled properties
489 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
490 template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
491 typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle>
493 typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
494 GraphProperty, EdgeListS>, T Bundle::*>::type
495 get(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
496 GraphProperty, EdgeListS>& g)
498 typedef typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty,
499 EdgeProperty, GraphProperty, EdgeListS>, T Bundle::*>::type
501 return result_type(&g, p);
504 template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
505 typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle>
507 typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
508 GraphProperty, EdgeListS>, T Bundle::*>::const_type
509 get(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
510 GraphProperty, EdgeListS> const & g)
512 typedef typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty,
513 EdgeProperty, GraphProperty, EdgeListS>, T Bundle::*>::const_type
515 return result_type(&g, p);
518 template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
519 typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle,
522 get(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
523 GraphProperty, EdgeListS> const & g, const Key& key)
525 return get(get(p, g), key);
528 template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
529 typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle,
532 put(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
533 GraphProperty, EdgeListS>& g, const Key& key, const T& value)
535 put(get(p, g), key, value);
544 #endif // BOOST_GRAPH_ADJACENCY_LIST_HPP