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 // TODO: Deprecating this requires some cooperation from Boost.Config. It's not
21 // a good idea to just refuse the inclusion because it could break otherwise
23 #if !defined BOOST_NO_HASH
24 # ifdef BOOST_HASH_SET_HEADER
25 # include BOOST_HASH_SET_HEADER
31 #if !defined BOOST_NO_SLIST
32 # ifdef BOOST_SLIST_HEADER
33 # include BOOST_SLIST_HEADER
39 #include <boost/graph/graph_traits.hpp>
40 #include <boost/graph/graph_selectors.hpp>
41 #include <boost/property_map/property_map.hpp>
42 #include <boost/mpl/if.hpp>
43 #include <boost/mpl/and.hpp>
44 #include <boost/mpl/not.hpp>
45 #include <boost/mpl/bool.hpp>
46 #include <boost/graph/detail/edge.hpp>
47 #include <boost/type_traits/is_same.hpp>
48 #include <boost/detail/workaround.hpp>
49 #include <boost/graph/properties.hpp>
50 #include <boost/graph/named_graph.hpp>
54 //===========================================================================
55 // Selectors for the VertexList and EdgeList template parameters of
56 // adjacency_list, and the container_gen traits class which is used
57 // to map the selectors to the container type used to implement the
60 // The main container_gen traits class uses partial specialization,
61 // so we also include a workaround.
63 #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
65 #if !defined BOOST_NO_SLIST
75 #if !defined BOOST_NO_HASH
78 struct hash_multisetS
{ };
79 struct hash_multimapS
{ };
82 template <class Selector
, class ValueType
>
83 struct container_gen
{ };
85 template <class ValueType
>
86 struct container_gen
<listS
, ValueType
> {
87 typedef std::list
<ValueType
> type
;
89 #if !defined BOOST_NO_SLIST
90 template <class ValueType
>
91 struct container_gen
<slistS
, ValueType
> {
92 typedef BOOST_STD_EXTENSION_NAMESPACE::slist
<ValueType
> type
;
95 template <class ValueType
>
96 struct container_gen
<vecS
, ValueType
> {
97 typedef std::vector
<ValueType
> type
;
100 template <class ValueType
>
101 struct container_gen
<mapS
, ValueType
> {
102 typedef std::set
<ValueType
> type
;
105 template <class ValueType
>
106 struct container_gen
<setS
, ValueType
> {
107 typedef std::set
<ValueType
> type
;
110 template <class ValueType
>
111 struct container_gen
<multisetS
, ValueType
> {
112 typedef std::multiset
<ValueType
> type
;
115 template <class ValueType
>
116 struct container_gen
<multimapS
, ValueType
> {
117 typedef std::multiset
<ValueType
> type
;
120 #if !defined BOOST_NO_HASH
121 template <class ValueType
>
122 struct container_gen
<hash_setS
, ValueType
> {
123 typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set
<ValueType
> type
;
126 template <class ValueType
>
127 struct container_gen
<hash_mapS
, ValueType
> {
128 typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set
<ValueType
> type
;
131 template <class ValueType
>
132 struct container_gen
<hash_multisetS
, ValueType
> {
133 typedef BOOST_STD_EXTENSION_NAMESPACE::hash_multiset
<ValueType
> type
;
136 template <class ValueType
>
137 struct container_gen
<hash_multimapS
, ValueType
> {
138 typedef BOOST_STD_EXTENSION_NAMESPACE::hash_multiset
<ValueType
> type
;
142 #else // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
144 #if !defined BOOST_NO_SLIST
147 struct bind_
{ typedef BOOST_STD_EXTENSION_NAMESPACE::slist
<T
> type
; };
153 struct bind_
{ typedef std::vector
<T
> type
; };
158 struct bind_
{ typedef std::list
<T
> type
; };
163 struct bind_
{ typedef std::set
<T
, std::less
<T
> > type
; };
169 struct bind_
{ typedef std::set
<T
, std::less
<T
> > type
; };
174 struct bind_
{ typedef std::multiset
<T
, std::less
<T
> > type
; };
179 struct bind_
{ typedef std::multiset
<T
, std::less
<T
> > type
; };
182 #if !defined BOOST_NO_HASH
185 struct bind_
{ typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set
<T
, std::less
<T
> > type
; };
190 struct bind_
{ typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set
<T
, std::less
<T
> > type
; };
193 struct hash_multisetS
{
195 struct bind_
{ typedef BOOST_STD_EXTENSION_NAMESPACE::hash_multiset
<T
, std::less
<T
> > type
; };
198 struct hash_multimapS
{
200 struct bind_
{ typedef BOOST_STD_EXTENSION_NAMESPACE::hash_multiset
<T
, std::less
<T
> > type
; };
204 template <class Selector
> struct container_selector
{
208 #define BOOST_CONTAINER_SELECTOR(NAME) \
209 template <> struct container_selector<NAME> { \
213 BOOST_CONTAINER_SELECTOR(vecS
);
214 BOOST_CONTAINER_SELECTOR(listS
);
215 BOOST_CONTAINER_SELECTOR(mapS
);
216 BOOST_CONTAINER_SELECTOR(setS
);
217 BOOST_CONTAINER_SELECTOR(multisetS
);
218 #if !defined BOOST_NO_HASH
219 BOOST_CONTAINER_SELECTOR(hash_mapS
);
221 #if !defined BOOST_NO_SLIST
222 BOOST_CONTAINER_SELECTOR(slistS
);
225 template <class Selector
, class ValueType
>
226 struct container_gen
{
227 typedef typename container_selector
<Selector
>::type Select
;
228 typedef typename
Select:: template bind_
<ValueType
>::type type
;
231 #endif // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
233 template <class StorageSelector
>
234 struct parallel_edge_traits
{ };
237 struct parallel_edge_traits
<vecS
> {
238 typedef allow_parallel_edge_tag type
; };
241 struct parallel_edge_traits
<listS
> {
242 typedef allow_parallel_edge_tag type
; };
244 #if !defined BOOST_NO_SLIST
246 struct parallel_edge_traits
<slistS
> {
247 typedef allow_parallel_edge_tag type
; };
251 struct parallel_edge_traits
<setS
> {
252 typedef disallow_parallel_edge_tag type
; };
255 struct parallel_edge_traits
<multisetS
> {
256 typedef allow_parallel_edge_tag type
; };
258 #if !defined BOOST_NO_HASH
260 struct parallel_edge_traits
<hash_setS
> {
261 typedef disallow_parallel_edge_tag type
;
265 // mapS is obsolete, replaced with setS
267 struct parallel_edge_traits
<mapS
> {
268 typedef disallow_parallel_edge_tag type
; };
270 #if !defined BOOST_NO_HASH
272 struct parallel_edge_traits
<hash_mapS
> {
273 typedef disallow_parallel_edge_tag type
;
278 template <class Directed
> struct is_random_access
{
279 enum { value
= false};
280 typedef mpl::false_ type
;
283 struct is_random_access
<vecS
> {
284 enum { value
= true };
285 typedef mpl::true_ type
;
288 } // namespace detail
292 //===========================================================================
293 // The adjacency_list_traits class, which provides a way to access
294 // some of the associated types of an adjacency_list type without
295 // having to first create the adjacency_list type. This is useful
296 // when trying to create interior vertex or edge properties who's
297 // value type is a vertex or edge descriptor.
299 template <class OutEdgeListS
= vecS
,
300 class VertexListS
= vecS
,
301 class DirectedS
= directedS
,
302 class EdgeListS
= listS
>
303 struct adjacency_list_traits
305 typedef typename
detail::is_random_access
<VertexListS
>::type
307 typedef typename
DirectedS::is_bidir_t is_bidir
;
308 typedef typename
DirectedS::is_directed_t is_directed
;
310 typedef typename
mpl::if_
<is_bidir
,
312 typename
mpl::if_
<is_directed
,
313 directed_tag
, undirected_tag
315 >::type directed_category
;
317 typedef typename parallel_edge_traits
<OutEdgeListS
>::type
318 edge_parallel_category
;
320 typedef std::size_t vertices_size_type
;
321 typedef void* vertex_ptr
;
322 typedef typename
mpl::if_
<is_rand_access
,
323 vertices_size_type
, vertex_ptr
>::type vertex_descriptor
;
324 typedef detail::edge_desc_impl
<directed_category
, vertex_descriptor
>
328 // Logic to figure out the edges_size_type
330 typedef typename container_gen
<EdgeListS
, dummy
>::type EdgeContainer
;
331 typedef typename
DirectedS::is_bidir_t BidirectionalT
;
332 typedef typename
DirectedS::is_directed_t DirectedT
;
333 typedef typename
mpl::and_
<DirectedT
,
334 typename
mpl::not_
<BidirectionalT
>::type
>::type on_edge_storage
;
336 typedef typename
mpl::if_
<on_edge_storage
,
337 std::size_t, typename
EdgeContainer::size_type
338 >::type edges_size_type
;
344 #include <boost/graph/detail/adjacency_list.hpp>
348 //===========================================================================
349 // The adjacency_list class.
352 template <class OutEdgeListS
= vecS
, // a Sequence or an AssociativeContainer
353 class VertexListS
= vecS
, // a Sequence or a RandomAccessContainer
354 class DirectedS
= directedS
,
355 class VertexProperty
= no_property
,
356 class EdgeProperty
= no_property
,
357 class GraphProperty
= no_property
,
358 class EdgeListS
= listS
>
360 : public detail::adj_list_gen
<
361 adjacency_list
<OutEdgeListS
,VertexListS
,DirectedS
,
362 VertexProperty
,EdgeProperty
,GraphProperty
,EdgeListS
>,
363 VertexListS
, OutEdgeListS
, DirectedS
,
364 #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
365 typename
detail::retag_property_list
<vertex_bundle_t
,
366 VertexProperty
>::type
,
367 typename
detail::retag_property_list
<edge_bundle_t
, EdgeProperty
>::type
,
369 VertexProperty
, EdgeProperty
,
371 GraphProperty
, EdgeListS
>::type
,
372 // Support for named vertices
373 public graph::maybe_named_graph
<
374 adjacency_list
<OutEdgeListS
,VertexListS
,DirectedS
,
375 VertexProperty
,EdgeProperty
,GraphProperty
,EdgeListS
>,
376 typename adjacency_list_traits
<OutEdgeListS
, VertexListS
, DirectedS
,
377 EdgeListS
>::vertex_descriptor
,
380 public: // TODO Remove me
381 #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
382 typedef typename
detail::retag_property_list
<vertex_bundle_t
,
383 VertexProperty
>::retagged
384 maybe_vertex_bundled
;
386 typedef typename
detail::retag_property_list
<edge_bundle_t
,
387 EdgeProperty
>::retagged
392 #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
393 typedef typename
detail::retag_property_list
<vertex_bundle_t
,
394 VertexProperty
>::type
395 vertex_property_type
;
396 typedef typename
detail::retag_property_list
<edge_bundle_t
,
400 // The types that are actually bundled
401 typedef typename
mpl::if_c
<(is_same
<maybe_vertex_bundled
, no_property
>::value
),
403 maybe_vertex_bundled
>::type vertex_bundled
;
404 typedef typename
mpl::if_c
<(is_same
<maybe_edge_bundled
, no_property
>::value
),
406 maybe_edge_bundled
>::type edge_bundled
;
408 typedef VertexProperty vertex_property_type
;
409 typedef EdgeProperty edge_property_type
;
410 typedef no_vertex_bundle vertex_bundled
;
411 typedef no_edge_bundle edge_bundled
;
415 typedef adjacency_list self
;
416 typedef typename
detail::adj_list_gen
<
417 self
, VertexListS
, OutEdgeListS
, DirectedS
,
418 vertex_property_type
, edge_property_type
, GraphProperty
, EdgeListS
422 typedef typename
Base::stored_vertex stored_vertex
;
423 typedef typename
Base::vertices_size_type vertices_size_type
;
424 typedef typename
Base::edges_size_type edges_size_type
;
425 typedef typename
Base::degree_size_type degree_size_type
;
426 typedef typename
Base::vertex_descriptor vertex_descriptor
;
427 typedef typename
Base::edge_descriptor edge_descriptor
;
428 typedef OutEdgeListS out_edge_list_selector
;
429 typedef VertexListS vertex_list_selector
;
430 typedef DirectedS directed_selector
;
431 typedef EdgeListS edge_list_selector
;
433 typedef GraphProperty graph_property_type
;
435 inline adjacency_list(const GraphProperty
& p
= GraphProperty())
438 inline adjacency_list(const adjacency_list
& x
)
439 : Base(x
), m_property(x
.m_property
) { }
441 inline adjacency_list
& operator=(const adjacency_list
& x
) {
442 // TBD: probably should give the strong guarantee
445 m_property
= x
.m_property
;
450 // Required by Mutable Graph
451 inline adjacency_list(vertices_size_type num_vertices
,
452 const GraphProperty
& p
= GraphProperty())
453 : Base(num_vertices
), m_property(p
) { }
455 #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
456 // Required by Iterator Constructible Graph
457 template <class EdgeIterator
>
458 inline adjacency_list(EdgeIterator first
, EdgeIterator last
,
459 vertices_size_type n
,
461 const GraphProperty
& p
= GraphProperty())
462 : Base(n
, first
, last
), m_property(p
) { }
464 template <class EdgeIterator
, class EdgePropertyIterator
>
465 inline adjacency_list(EdgeIterator first
, EdgeIterator last
,
466 EdgePropertyIterator ep_iter
,
467 vertices_size_type n
,
469 const GraphProperty
& p
= GraphProperty())
470 : Base(n
, first
, last
, ep_iter
), m_property(p
) { }
473 void swap(adjacency_list
& x
) {
474 // Is there a more efficient way to do this?
475 adjacency_list
tmp(x
);
482 this->clearing_graph();
486 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
487 // Directly access a vertex or edge bundle
488 vertex_bundled
& operator[](vertex_descriptor v
)
489 { return get(vertex_bundle
, *this)[v
]; }
491 const vertex_bundled
& operator[](vertex_descriptor v
) const
492 { return get(vertex_bundle
, *this)[v
]; }
494 edge_bundled
& operator[](edge_descriptor e
)
495 { return get(edge_bundle
, *this)[e
]; }
497 const edge_bundled
& operator[](edge_descriptor e
) const
498 { return get(edge_bundle
, *this)[e
]; }
501 // protected: (would be protected if friends were more portable)
502 GraphProperty m_property
;
505 template <class OEL
, class VL
, class DirS
, class VP
,class EP
, class GP
,
506 class EL
, class Tag
, class Value
>
508 set_property(adjacency_list
<OEL
,VL
,DirS
,VP
,EP
,GP
,EL
>& g
, Tag
,
509 const Value
& value
) {
510 get_property_value(g
.m_property
, Tag()) = value
;;
513 template <class OEL
, class VL
, class DirS
, class VP
, class EP
, class GP
,
516 typename graph_property
<adjacency_list
<OEL
,VL
,DirS
,VP
,EP
,GP
,EL
>, Tag
>::type
&
517 get_property(adjacency_list
<OEL
,VL
,DirS
,VP
,EP
,GP
,EL
>& g
, Tag
) {
518 return get_property_value(g
.m_property
, Tag());
521 template <class OEL
, class VL
, class DirS
, class VP
, class EP
, class GP
,
525 typename graph_property
<adjacency_list
<OEL
,VL
,DirS
,VP
,EP
,GP
,EL
>, Tag
>::type
&
526 get_property(const adjacency_list
<OEL
,VL
,DirS
,VP
,EP
,GP
,EL
>& g
, Tag
) {
527 return get_property_value(g
.m_property
, Tag());
530 // dwa 09/25/00 - needed to be more explicit so reverse_graph would work.
531 template <class Directed
, class Vertex
,
535 class VertexProperty
,
537 class GraphProperty
, class EdgeListS
>
539 source(const detail::edge_base
<Directed
,Vertex
>& e
,
540 const adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
,
541 VertexProperty
, EdgeProperty
, GraphProperty
, EdgeListS
>&)
546 template <class Directed
, class Vertex
, class OutEdgeListS
,
547 class VertexListS
, class DirectedS
, class VertexProperty
,
548 class EdgeProperty
, class GraphProperty
, class EdgeListS
>
550 target(const detail::edge_base
<Directed
,Vertex
>& e
,
551 const adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
,
552 VertexProperty
, EdgeProperty
, GraphProperty
, EdgeListS
>&)
557 // Support for bundled properties
558 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
559 template<typename OutEdgeListS
, typename VertexListS
, typename DirectedS
, typename VertexProperty
,
560 typename EdgeProperty
, typename GraphProperty
, typename EdgeListS
, typename T
, typename Bundle
>
562 typename property_map
<adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
, EdgeProperty
,
563 GraphProperty
, EdgeListS
>, T
Bundle::*>::type
564 get(T
Bundle::* p
, adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
, EdgeProperty
,
565 GraphProperty
, EdgeListS
>& g
)
567 typedef typename property_map
<adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
,
568 EdgeProperty
, GraphProperty
, EdgeListS
>, T
Bundle::*>::type
570 return result_type(&g
, p
);
573 template<typename OutEdgeListS
, typename VertexListS
, typename DirectedS
, typename VertexProperty
,
574 typename EdgeProperty
, typename GraphProperty
, typename EdgeListS
, typename T
, typename Bundle
>
576 typename property_map
<adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
, EdgeProperty
,
577 GraphProperty
, EdgeListS
>, T
Bundle::*>::const_type
578 get(T
Bundle::* p
, adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
, EdgeProperty
,
579 GraphProperty
, EdgeListS
> const & g
)
581 typedef typename property_map
<adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
,
582 EdgeProperty
, GraphProperty
, EdgeListS
>, T
Bundle::*>::const_type
584 return result_type(&g
, p
);
587 template<typename OutEdgeListS
, typename VertexListS
, typename DirectedS
, typename VertexProperty
,
588 typename EdgeProperty
, typename GraphProperty
, typename EdgeListS
, typename T
, typename Bundle
,
591 get(T
Bundle::* p
, adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
, EdgeProperty
,
592 GraphProperty
, EdgeListS
> const & g
, const Key
& key
)
594 return get(get(p
, g
), key
);
597 template<typename OutEdgeListS
, typename VertexListS
, typename DirectedS
, typename VertexProperty
,
598 typename EdgeProperty
, typename GraphProperty
, typename EdgeListS
, typename T
, typename Bundle
,
601 put(T
Bundle::* p
, adjacency_list
<OutEdgeListS
, VertexListS
, DirectedS
, VertexProperty
, EdgeProperty
,
602 GraphProperty
, EdgeListS
>& g
, const Key
& key
, const T
& value
)
604 put(get(p
, g
), key
, value
);
613 #endif // BOOST_GRAPH_ADJACENCY_LIST_HPP