Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:10

0001 // -*- c++ -*-
0002 //=======================================================================
0003 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
0004 // Copyright 2010 Thomas Claveirole
0005 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See
0008 // accompanying file LICENSE_1_0.txt or copy at
0009 // http://www.boost.org/LICENSE_1_0.txt)
0010 //=======================================================================
0011 
0012 #ifndef BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP
0013 #define BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP
0014 
0015 #include <map> // for vertex_map in copy_impl
0016 #include <boost/config.hpp>
0017 #include <boost/detail/workaround.hpp>
0018 #include <boost/operators.hpp>
0019 #include <boost/property_map/property_map.hpp>
0020 #include <boost/pending/container_traits.hpp>
0021 #include <boost/range/irange.hpp>
0022 #include <boost/graph/graph_traits.hpp>
0023 #include <memory>
0024 #include <iterator>
0025 #include <algorithm>
0026 #include <boost/limits.hpp>
0027 
0028 #include <boost/iterator/iterator_adaptor.hpp>
0029 
0030 #include <boost/mpl/if.hpp>
0031 #include <boost/mpl/not.hpp>
0032 #include <boost/mpl/and.hpp>
0033 #include <boost/graph/graph_concepts.hpp>
0034 #include <boost/pending/container_traits.hpp>
0035 #include <boost/graph/detail/adj_list_edge_iterator.hpp>
0036 #include <boost/graph/properties.hpp>
0037 #include <boost/pending/property.hpp>
0038 #include <boost/graph/adjacency_iterator.hpp>
0039 #include <boost/static_assert.hpp>
0040 #include <boost/assert.hpp>
0041 
0042 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0043 #define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (x)
0044 #else
0045 #include <utility>
0046 #define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (std::move((x)))
0047 #endif
0048 
0049 /*
0050   Outline for this file:
0051 
0052   out_edge_iterator and in_edge_iterator implementation
0053   edge_iterator for undirected graph
0054   stored edge types (these object live in the out-edge/in-edge lists)
0055   directed edges helper class
0056   directed graph helper class
0057   undirected graph helper class
0058   bidirectional graph helper class
0059   bidirectional graph helper class (without edge properties)
0060   bidirectional graph helper class (with edge properties)
0061   adjacency_list helper class
0062   adj_list_impl class
0063   vec_adj_list_impl class
0064   adj_list_gen class
0065   vertex property map
0066   edge property map
0067 
0068 
0069   Note: it would be nice to merge some of the undirected and
0070   bidirectional code... it is awful similar.
0071  */
0072 
0073 namespace boost
0074 {
0075 
0076 namespace detail
0077 {
0078 
0079     template < typename DirectedS > struct directed_category_traits
0080     {
0081         typedef directed_tag directed_category;
0082     };
0083 
0084     template <> struct directed_category_traits< directedS >
0085     {
0086         typedef directed_tag directed_category;
0087     };
0088     template <> struct directed_category_traits< undirectedS >
0089     {
0090         typedef undirected_tag directed_category;
0091     };
0092     template <> struct directed_category_traits< bidirectionalS >
0093     {
0094         typedef bidirectional_tag directed_category;
0095     };
0096 
0097     template < class Vertex > struct target_is
0098     {
0099         target_is(const Vertex& v) : m_target(v) {}
0100         template < class StoredEdge > bool operator()(const StoredEdge& e) const
0101         {
0102             return e.get_target() == m_target;
0103         }
0104         Vertex m_target;
0105     };
0106 
0107     // O(E/V)
0108     template < class EdgeList, class vertex_descriptor >
0109     void erase_from_incidence_list(
0110         EdgeList& el, vertex_descriptor v, allow_parallel_edge_tag)
0111     {
0112         boost::graph_detail::erase_if(
0113             el, detail::target_is< vertex_descriptor >(v));
0114     }
0115     // O(log(E/V))
0116     template < class EdgeList, class vertex_descriptor >
0117     void erase_from_incidence_list(
0118         EdgeList& el, vertex_descriptor v, disallow_parallel_edge_tag)
0119     {
0120         typedef typename EdgeList::value_type StoredEdge;
0121         el.erase(StoredEdge(v));
0122     }
0123 
0124     //=========================================================================
0125     // Out-Edge and In-Edge Iterator Implementation
0126 
0127     template < class BaseIter, class VertexDescriptor, class EdgeDescriptor,
0128         class Difference >
0129     struct out_edge_iter
0130     : iterator_adaptor< out_edge_iter< BaseIter, VertexDescriptor,
0131                             EdgeDescriptor, Difference >,
0132           BaseIter, EdgeDescriptor, use_default, EdgeDescriptor, Difference >
0133     {
0134         typedef iterator_adaptor< out_edge_iter< BaseIter, VertexDescriptor,
0135                                       EdgeDescriptor, Difference >,
0136             BaseIter, EdgeDescriptor, use_default, EdgeDescriptor, Difference >
0137             super_t;
0138 
0139         inline out_edge_iter() {}
0140         inline out_edge_iter(const BaseIter& i, const VertexDescriptor& src)
0141         : super_t(i), m_src(src)
0142         {
0143         }
0144 
0145         inline EdgeDescriptor dereference() const
0146         {
0147             return EdgeDescriptor(m_src, (*this->base()).get_target(),
0148                 &(*this->base()).get_property());
0149         }
0150         VertexDescriptor m_src;
0151     };
0152 
0153     template < class BaseIter, class VertexDescriptor, class EdgeDescriptor,
0154         class Difference >
0155     struct in_edge_iter
0156     : iterator_adaptor< in_edge_iter< BaseIter, VertexDescriptor,
0157                             EdgeDescriptor, Difference >,
0158           BaseIter, EdgeDescriptor, use_default, EdgeDescriptor, Difference >
0159     {
0160         typedef iterator_adaptor< in_edge_iter< BaseIter, VertexDescriptor,
0161                                       EdgeDescriptor, Difference >,
0162             BaseIter, EdgeDescriptor, use_default, EdgeDescriptor, Difference >
0163             super_t;
0164 
0165         inline in_edge_iter() {}
0166         inline in_edge_iter(const BaseIter& i, const VertexDescriptor& src)
0167         : super_t(i), m_src(src)
0168         {
0169         }
0170 
0171         inline EdgeDescriptor dereference() const
0172         {
0173             return EdgeDescriptor((*this->base()).get_target(), m_src,
0174                 &this->base()->get_property());
0175         }
0176         VertexDescriptor m_src;
0177     };
0178 
0179     //=========================================================================
0180     // Undirected Edge Iterator Implementation
0181 
0182     template < class EdgeIter, class EdgeDescriptor, class Difference >
0183     struct undirected_edge_iter
0184     : iterator_adaptor<
0185           undirected_edge_iter< EdgeIter, EdgeDescriptor, Difference >,
0186           EdgeIter, EdgeDescriptor, use_default, EdgeDescriptor, Difference >
0187     {
0188         typedef iterator_adaptor<
0189             undirected_edge_iter< EdgeIter, EdgeDescriptor, Difference >,
0190             EdgeIter, EdgeDescriptor, use_default, EdgeDescriptor, Difference >
0191             super_t;
0192 
0193         undirected_edge_iter() {}
0194 
0195         explicit undirected_edge_iter(EdgeIter i) : super_t(i) {}
0196 
0197         inline EdgeDescriptor dereference() const
0198         {
0199             return EdgeDescriptor((*this->base()).m_source,
0200                 (*this->base()).m_target, &this->base()->get_property());
0201         }
0202     };
0203 
0204     //=========================================================================
0205     // Edge Storage Types (stored in the out-edge/in-edge lists)
0206 
0207     template < class Vertex >
0208     class stored_edge
0209     : public boost::equality_comparable1< stored_edge< Vertex >,
0210           boost::less_than_comparable1< stored_edge< Vertex > > >
0211     {
0212     public:
0213         typedef no_property property_type;
0214         inline stored_edge() {}
0215         inline stored_edge(Vertex target, const no_property& = no_property())
0216         : m_target(target)
0217         {
0218         }
0219         inline Vertex& get_target() const { return m_target; }
0220         inline const no_property& get_property() const { return s_prop; }
0221         inline bool operator==(const stored_edge& x) const
0222         {
0223             return m_target == x.get_target();
0224         }
0225         inline bool operator<(const stored_edge& x) const
0226         {
0227             return m_target < x.get_target();
0228         }
0229         // protected: need to add hash<> as a friend
0230         static no_property s_prop;
0231         // Sometimes target not used as key in the set, and in that case
0232         // it is ok to change the target.
0233         mutable Vertex m_target;
0234     };
0235     template < class Vertex > no_property stored_edge< Vertex >::s_prop;
0236 
0237 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \
0238     || defined(BOOST_NO_CXX11_SMART_PTR)
0239     template < class Vertex, class Property >
0240     class stored_edge_property : public stored_edge< Vertex >
0241     {
0242         typedef stored_edge_property self;
0243         typedef stored_edge< Vertex > Base;
0244 
0245     public:
0246         typedef Property property_type;
0247         inline stored_edge_property() {}
0248         inline stored_edge_property(
0249             Vertex target, const Property& p = Property())
0250         : stored_edge< Vertex >(target), m_property(new Property(p))
0251         {
0252         }
0253         stored_edge_property(const self& x)
0254         : Base(static_cast< Base const& >(x))
0255         , m_property(const_cast< self& >(x).m_property)
0256         {
0257         }
0258         self& operator=(const self& x)
0259         {
0260             // NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug
0261             // 55771 of Mozilla).
0262             static_cast< Base& >(*this) = static_cast< Base const& >(x);
0263             m_property = const_cast< self& >(x).m_property;
0264             return *this;
0265         }
0266 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0267         // NOTE Don't rely on default operators, their behavior is broken on
0268         // several compilers (GCC 4.6).
0269         stored_edge_property(self&& x)
0270         : Base(static_cast< Base&& >(x)), m_property(std::move(x.m_property))
0271         {
0272         }
0273         self& operator=(self&& x)
0274         {
0275             // NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug
0276             // 55771 of Mozilla).
0277             static_cast< Base& >(*this) = static_cast< Base&& >(x);
0278             m_property = std::move(x.m_property);
0279             return *this;
0280         }
0281 #endif
0282         inline Property& get_property() { return *m_property; }
0283         inline const Property& get_property() const { return *m_property; }
0284 
0285     protected:
0286         // Holding the property by-value causes edge-descriptor
0287         // invalidation for add_edge() with EdgeList=vecS. Instead we
0288         // hold a pointer to the property. std::auto_ptr is not
0289         // a perfect fit for the job, but it is darn close.
0290 #ifdef BOOST_NO_AUTO_PTR
0291         std::unique_ptr< Property > m_property;
0292 #else
0293         std::auto_ptr< Property > m_property;
0294 #endif
0295     };
0296 #else
0297     template < class Vertex, class Property >
0298     class stored_edge_property : public stored_edge< Vertex >
0299     {
0300         typedef stored_edge_property self;
0301         typedef stored_edge< Vertex > Base;
0302 
0303     public:
0304         typedef Property property_type;
0305         inline stored_edge_property() {}
0306         inline stored_edge_property(
0307             Vertex target, const Property& p = Property())
0308         : stored_edge< Vertex >(target), m_property(new Property(p))
0309         {
0310         }
0311         stored_edge_property(self&& x)
0312         : Base(static_cast< Base&& >(x)), m_property(std::move(x.m_property))
0313         {
0314         }
0315         stored_edge_property(self const& x)
0316         : Base(static_cast< Base const& >(x))
0317         , m_property(std::move(const_cast< self& >(x).m_property))
0318         {
0319         }
0320         self& operator=(self&& x)
0321         {
0322             // NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug
0323             // 55771 of Mozilla).
0324             static_cast< Base& >(*this) = static_cast< Base&& >(x);
0325             m_property = std::move(x.m_property);
0326             return *this;
0327         }
0328         self& operator=(self const& x)
0329         {
0330             // NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug
0331             // 55771 of Mozilla).
0332             static_cast< Base& >(*this) = static_cast< Base const& >(x);
0333             m_property = std::move(const_cast< self& >(x).m_property);
0334             return *this;
0335         }
0336         inline Property& get_property() { return *m_property; }
0337         inline const Property& get_property() const { return *m_property; }
0338 
0339     protected:
0340         std::unique_ptr< Property > m_property;
0341     };
0342 #endif
0343 
0344     template < class Vertex, class Iter, class Property >
0345     class stored_edge_iter : public stored_edge< Vertex >
0346     {
0347     public:
0348         typedef Property property_type;
0349         inline stored_edge_iter() {}
0350         inline stored_edge_iter(Vertex v) : stored_edge< Vertex >(v) {}
0351         inline stored_edge_iter(Vertex v, Iter i, void* = 0)
0352         : stored_edge< Vertex >(v), m_iter(i)
0353         {
0354         }
0355         inline Property& get_property() { return m_iter->get_property(); }
0356         inline const Property& get_property() const
0357         {
0358             return m_iter->get_property();
0359         }
0360         inline Iter get_iter() const { return m_iter; }
0361 
0362     protected:
0363         Iter m_iter;
0364     };
0365 
0366     // For when the EdgeList is a std::vector.
0367     // Want to make the iterator stable, so use an offset
0368     // instead of an iterator into a std::vector
0369     template < class Vertex, class EdgeVec, class Property >
0370     class stored_ra_edge_iter : public stored_edge< Vertex >
0371     {
0372         typedef typename EdgeVec::iterator Iter;
0373 
0374     public:
0375         typedef Property property_type;
0376         inline stored_ra_edge_iter() {}
0377         inline explicit stored_ra_edge_iter(
0378             Vertex v) // Only used for comparisons
0379         : stored_edge< Vertex >(v), m_i(0), m_vec(0)
0380         {
0381         }
0382         inline stored_ra_edge_iter(Vertex v, Iter i, EdgeVec* edge_vec)
0383         : stored_edge< Vertex >(v), m_i(i - edge_vec->begin()), m_vec(edge_vec)
0384         {
0385         }
0386         inline Property& get_property()
0387         {
0388             BOOST_ASSERT((m_vec != 0));
0389             return (*m_vec)[m_i].get_property();
0390         }
0391         inline const Property& get_property() const
0392         {
0393             BOOST_ASSERT((m_vec != 0));
0394             return (*m_vec)[m_i].get_property();
0395         }
0396         inline Iter get_iter() const
0397         {
0398             BOOST_ASSERT((m_vec != 0));
0399             return m_vec->begin() + m_i;
0400         }
0401 
0402     protected:
0403         std::size_t m_i;
0404         EdgeVec* m_vec;
0405     };
0406 
0407 } // namespace detail
0408 
0409 template < class Tag, class Vertex, class Property >
0410 const typename property_value< Property, Tag >::type& get(
0411     Tag property_tag, const detail::stored_edge_property< Vertex, Property >& e)
0412 {
0413     return get_property_value(e.get_property(), property_tag);
0414 }
0415 
0416 template < class Tag, class Vertex, class Iter, class Property >
0417 const typename property_value< Property, Tag >::type& get(Tag property_tag,
0418     const detail::stored_edge_iter< Vertex, Iter, Property >& e)
0419 {
0420     return get_property_value(e.get_property(), property_tag);
0421 }
0422 
0423 template < class Tag, class Vertex, class EdgeVec, class Property >
0424 const typename property_value< Property, Tag >::type& get(Tag property_tag,
0425     const detail::stored_ra_edge_iter< Vertex, EdgeVec, Property >& e)
0426 {
0427     return get_property_value(e.get_property(), property_tag);
0428 }
0429 
0430 //=========================================================================
0431 // Directed Edges Helper Class
0432 
0433 namespace detail
0434 {
0435 
0436     // O(E/V)
0437     template < class edge_descriptor, class EdgeList, class StoredProperty >
0438     inline void remove_directed_edge_dispatch(
0439         edge_descriptor, EdgeList& el, StoredProperty& p)
0440     {
0441         for (typename EdgeList::iterator i = el.begin(); i != el.end(); ++i)
0442             if (&(*i).get_property() == &p)
0443             {
0444                 el.erase(i);
0445                 return;
0446             }
0447     }
0448 
0449     template < class incidence_iterator, class EdgeList, class Predicate >
0450     inline void remove_directed_edge_if_dispatch(incidence_iterator first,
0451         incidence_iterator last, EdgeList& el, Predicate pred,
0452         boost::allow_parallel_edge_tag)
0453     {
0454         // remove_if
0455         while (first != last && !pred(*first))
0456             ++first;
0457         incidence_iterator i = first;
0458         if (first != last)
0459             for (++i; i != last; ++i)
0460                 if (!pred(*i))
0461                 {
0462                     *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base());
0463                     ++first;
0464                 }
0465         el.erase(first.base(), el.end());
0466     }
0467     template < class incidence_iterator, class EdgeList, class Predicate >
0468     inline void remove_directed_edge_if_dispatch(incidence_iterator first,
0469         incidence_iterator last, EdgeList& el, Predicate pred,
0470         boost::disallow_parallel_edge_tag)
0471     {
0472         for (incidence_iterator next = first; first != last; first = next)
0473         {
0474             ++next;
0475             if (pred(*first))
0476                 el.erase(first.base());
0477         }
0478     }
0479 
0480     template < class PropT, class Graph, class incidence_iterator,
0481         class EdgeList, class Predicate >
0482     inline void undirected_remove_out_edge_if_dispatch(Graph& g,
0483         incidence_iterator first, incidence_iterator last, EdgeList& el,
0484         Predicate pred, boost::allow_parallel_edge_tag)
0485     {
0486         typedef typename Graph::global_edgelist_selector EdgeListS;
0487         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0488 
0489         // remove_if
0490         while (first != last && !pred(*first))
0491             ++first;
0492         incidence_iterator i = first;
0493         bool self_loop_removed = false;
0494         if (first != last)
0495             for (; i != last; ++i)
0496             {
0497                 if (self_loop_removed)
0498                 {
0499                     /* With self loops, the descriptor will show up
0500                      * twice. The first time it will be removed, and now it
0501                      * will be skipped.
0502                      */
0503                     self_loop_removed = false;
0504                 }
0505                 else if (!pred(*i))
0506                 {
0507                     *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base());
0508                     ++first;
0509                 }
0510                 else
0511                 {
0512                     if (source(*i, g) == target(*i, g))
0513                         self_loop_removed = true;
0514                     else
0515                     {
0516                         // Remove the edge from the target
0517                         detail::remove_directed_edge_dispatch(*i,
0518                             g.out_edge_list(target(*i, g)),
0519                             *(PropT*)(*i).get_property());
0520                     }
0521 
0522                     // Erase the edge property
0523                     g.m_edges.erase((*i.base()).get_iter());
0524                 }
0525             }
0526         el.erase(first.base(), el.end());
0527     }
0528     template < class PropT, class Graph, class incidence_iterator,
0529         class EdgeList, class Predicate >
0530     inline void undirected_remove_out_edge_if_dispatch(Graph& g,
0531         incidence_iterator first, incidence_iterator last, EdgeList& el,
0532         Predicate pred, boost::disallow_parallel_edge_tag)
0533     {
0534         typedef typename Graph::global_edgelist_selector EdgeListS;
0535         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0536 
0537         for (incidence_iterator next = first; first != last; first = next)
0538         {
0539             ++next;
0540             if (pred(*first))
0541             {
0542                 if (source(*first, g) != target(*first, g))
0543                 {
0544                     // Remove the edge from the target
0545                     detail::remove_directed_edge_dispatch(*first,
0546                         g.out_edge_list(target(*first, g)),
0547                         *(PropT*)(*first).get_property());
0548                 }
0549 
0550                 // Erase the edge property
0551                 g.m_edges.erase((*first.base()).get_iter());
0552 
0553                 // Erase the edge in the source
0554                 el.erase(first.base());
0555             }
0556         }
0557     }
0558 
0559     // O(E/V)
0560     template < class edge_descriptor, class EdgeList, class StoredProperty >
0561     inline void remove_directed_edge_dispatch(
0562         edge_descriptor e, EdgeList& el, no_property&)
0563     {
0564         for (typename EdgeList::iterator i = el.begin(); i != el.end(); ++i)
0565             if ((*i).get_target() == e.m_target)
0566             {
0567                 el.erase(i);
0568                 return;
0569             }
0570     }
0571 
0572 } // namespace detail
0573 
0574 template < class Config > struct directed_edges_helper
0575 {
0576 
0577     // Placement of these overloaded remove_edge() functions
0578     // inside the class avoids a VC++ bug.
0579 
0580     // O(E/V)
0581     inline void remove_edge(typename Config::edge_descriptor e)
0582     {
0583         typedef typename Config::graph_type graph_type;
0584         graph_type& g = static_cast< graph_type& >(*this);
0585         typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
0586         typedef typename Config::OutEdgeList::value_type::property_type PType;
0587         detail::remove_directed_edge_dispatch(e, el, *(PType*)e.get_property());
0588     }
0589 
0590     // O(1)
0591     inline void remove_edge(typename Config::out_edge_iterator iter)
0592     {
0593         typedef typename Config::graph_type graph_type;
0594         graph_type& g = static_cast< graph_type& >(*this);
0595         typename Config::edge_descriptor e = *iter;
0596         typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
0597         el.erase(iter.base());
0598     }
0599 };
0600 
0601 // O(1)
0602 template < class Config >
0603 inline std::pair< typename Config::edge_iterator,
0604     typename Config::edge_iterator >
0605 edges(const directed_edges_helper< Config >& g_)
0606 {
0607     typedef typename Config::graph_type graph_type;
0608     typedef typename Config::edge_iterator edge_iterator;
0609     const graph_type& cg = static_cast< const graph_type& >(g_);
0610     graph_type& g = const_cast< graph_type& >(cg);
0611     return std::make_pair(edge_iterator(g.vertex_set().begin(),
0612                               g.vertex_set().begin(), g.vertex_set().end(), g),
0613         edge_iterator(g.vertex_set().begin(), g.vertex_set().end(),
0614             g.vertex_set().end(), g));
0615 }
0616 
0617 //=========================================================================
0618 // Directed Graph Helper Class
0619 
0620 struct adj_list_dir_traversal_tag : public virtual vertex_list_graph_tag,
0621                                     public virtual incidence_graph_tag,
0622                                     public virtual adjacency_graph_tag,
0623                                     public virtual edge_list_graph_tag
0624 {
0625 };
0626 
0627 template < class Config >
0628 struct directed_graph_helper : public directed_edges_helper< Config >
0629 {
0630     typedef typename Config::edge_descriptor edge_descriptor;
0631     typedef adj_list_dir_traversal_tag traversal_category;
0632 };
0633 
0634 // O(E/V)
0635 template < class Config >
0636 inline void remove_edge(typename Config::vertex_descriptor u,
0637     typename Config::vertex_descriptor v, directed_graph_helper< Config >& g_)
0638 {
0639     typedef typename Config::graph_type graph_type;
0640     typedef typename Config::edge_parallel_category Cat;
0641     graph_type& g = static_cast< graph_type& >(g_);
0642     detail::erase_from_incidence_list(g.out_edge_list(u), v, Cat());
0643 }
0644 
0645 template < class Config, class Predicate >
0646 inline void remove_out_edge_if(typename Config::vertex_descriptor u,
0647     Predicate pred, directed_graph_helper< Config >& g_)
0648 {
0649     typedef typename Config::graph_type graph_type;
0650     graph_type& g = static_cast< graph_type& >(g_);
0651     typename Config::out_edge_iterator first, last;
0652     boost::tie(first, last) = out_edges(u, g);
0653     typedef typename Config::edge_parallel_category edge_parallel_category;
0654     detail::remove_directed_edge_if_dispatch(
0655         first, last, g.out_edge_list(u), pred, edge_parallel_category());
0656 }
0657 
0658 template < class Config, class Predicate >
0659 inline void remove_edge_if(Predicate pred, directed_graph_helper< Config >& g_)
0660 {
0661     typedef typename Config::graph_type graph_type;
0662     graph_type& g = static_cast< graph_type& >(g_);
0663 
0664     typename Config::vertex_iterator vi, vi_end;
0665     for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0666         remove_out_edge_if(*vi, pred, g);
0667 }
0668 
0669 template < class EdgeOrIter, class Config >
0670 inline void remove_edge(
0671     EdgeOrIter e_or_iter, directed_graph_helper< Config >& g_)
0672 {
0673     g_.remove_edge(e_or_iter);
0674 }
0675 
0676 // O(V + E) for allow_parallel_edges
0677 // O(V * log(E/V)) for disallow_parallel_edges
0678 template < class Config >
0679 inline void clear_vertex(
0680     typename Config::vertex_descriptor u, directed_graph_helper< Config >& g_)
0681 {
0682     typedef typename Config::graph_type graph_type;
0683     typedef typename Config::edge_parallel_category Cat;
0684     graph_type& g = static_cast< graph_type& >(g_);
0685     typename Config::vertex_iterator vi, viend;
0686     for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
0687         detail::erase_from_incidence_list(g.out_edge_list(*vi), u, Cat());
0688     g.out_edge_list(u).clear();
0689     // clear() should be a req of Sequence and AssociativeContainer,
0690     // or maybe just Container
0691 }
0692 
0693 template < class Config >
0694 inline void clear_out_edges(
0695     typename Config::vertex_descriptor u, directed_graph_helper< Config >& g_)
0696 {
0697     typedef typename Config::graph_type graph_type;
0698     graph_type& g = static_cast< graph_type& >(g_);
0699     g.out_edge_list(u).clear();
0700     // clear() should be a req of Sequence and AssociativeContainer,
0701     // or maybe just Container
0702 }
0703 
0704 // O(V), could do better...
0705 template < class Config >
0706 inline typename Config::edges_size_type num_edges(
0707     const directed_graph_helper< Config >& g_)
0708 {
0709     typedef typename Config::graph_type graph_type;
0710     const graph_type& g = static_cast< const graph_type& >(g_);
0711     typename Config::edges_size_type num_e = 0;
0712     typename Config::vertex_iterator vi, vi_end;
0713     for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0714         num_e += out_degree(*vi, g);
0715     return num_e;
0716 }
0717 // O(1) for allow_parallel_edge_tag
0718 // O(log(E/V)) for disallow_parallel_edge_tag
0719 template < class Config >
0720 inline std::pair< typename directed_graph_helper< Config >::edge_descriptor,
0721     bool >
0722 add_edge(typename Config::vertex_descriptor u,
0723     typename Config::vertex_descriptor v,
0724     const typename Config::edge_property_type& p,
0725     directed_graph_helper< Config >& g_)
0726 {
0727     typedef typename Config::edge_descriptor edge_descriptor;
0728     typedef typename Config::graph_type graph_type;
0729     typedef typename Config::StoredEdge StoredEdge;
0730     graph_type& g = static_cast< graph_type& >(g_);
0731     typename Config::OutEdgeList::iterator i;
0732     bool inserted;
0733     boost::tie(i, inserted)
0734         = boost::graph_detail::push(g.out_edge_list(u), StoredEdge(v, p));
0735     return std::make_pair(
0736         edge_descriptor(u, v, &(*i).get_property()), inserted);
0737 }
0738 // Did not use default argument here because that
0739 // causes Visual C++ to get confused.
0740 template < class Config >
0741 inline std::pair< typename Config::edge_descriptor, bool > add_edge(
0742     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
0743     directed_graph_helper< Config >& g_)
0744 {
0745     typename Config::edge_property_type p;
0746     return add_edge(u, v, p, g_);
0747 }
0748 //=========================================================================
0749 // Undirected Graph Helper Class
0750 
0751 template < class Config > struct undirected_graph_helper;
0752 
0753 struct undir_adj_list_traversal_tag : public virtual vertex_list_graph_tag,
0754                                       public virtual incidence_graph_tag,
0755                                       public virtual adjacency_graph_tag,
0756                                       public virtual edge_list_graph_tag,
0757                                       public virtual bidirectional_graph_tag
0758 {
0759 };
0760 
0761 namespace detail
0762 {
0763 
0764     // using class with specialization for dispatch is a VC++ workaround.
0765     template < class StoredProperty > struct remove_undirected_edge_dispatch
0766     {
0767 
0768         // O(E/V)
0769         template < class edge_descriptor, class Config >
0770         static void apply(edge_descriptor e,
0771             undirected_graph_helper< Config >& g_, StoredProperty& p)
0772         {
0773             typedef typename Config::global_edgelist_selector EdgeListS;
0774             BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0775 
0776             typedef typename Config::graph_type graph_type;
0777             graph_type& g = static_cast< graph_type& >(g_);
0778 
0779             typename Config::OutEdgeList& out_el
0780                 = g.out_edge_list(source(e, g));
0781             typename Config::OutEdgeList::iterator out_i = out_el.begin();
0782             typename Config::EdgeIter edge_iter_to_erase;
0783             for (; out_i != out_el.end(); ++out_i)
0784                 if (&(*out_i).get_property() == &p)
0785                 {
0786                     edge_iter_to_erase = (*out_i).get_iter();
0787                     out_el.erase(out_i);
0788                     break;
0789                 }
0790             typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
0791             typename Config::OutEdgeList::iterator in_i = in_el.begin();
0792             for (; in_i != in_el.end(); ++in_i)
0793                 if (&(*in_i).get_property() == &p)
0794                 {
0795                     in_el.erase(in_i);
0796                     break;
0797                 }
0798             g.m_edges.erase(edge_iter_to_erase);
0799         }
0800     };
0801 
0802     template <> struct remove_undirected_edge_dispatch< no_property >
0803     {
0804         // O(E/V)
0805         template < class edge_descriptor, class Config >
0806         static void apply(edge_descriptor e,
0807             undirected_graph_helper< Config >& g_, no_property&)
0808         {
0809             typedef typename Config::global_edgelist_selector EdgeListS;
0810             BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0811 
0812             typedef typename Config::graph_type graph_type;
0813             graph_type& g = static_cast< graph_type& >(g_);
0814             no_property* p = (no_property*)e.get_property();
0815             typename Config::OutEdgeList& out_el
0816                 = g.out_edge_list(source(e, g));
0817             typename Config::OutEdgeList::iterator out_i = out_el.begin();
0818             typename Config::EdgeIter edge_iter_to_erase;
0819             for (; out_i != out_el.end(); ++out_i)
0820                 if (&(*out_i).get_property() == p)
0821                 {
0822                     edge_iter_to_erase = (*out_i).get_iter();
0823                     out_el.erase(out_i);
0824                     break;
0825                 }
0826             typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
0827             typename Config::OutEdgeList::iterator in_i = in_el.begin();
0828             for (; in_i != in_el.end(); ++in_i)
0829                 if (&(*in_i).get_property() == p)
0830                 {
0831                     in_el.erase(in_i);
0832                     break;
0833                 }
0834             g.m_edges.erase(edge_iter_to_erase);
0835         }
0836     };
0837 
0838     // O(E/V)
0839     template < class Graph, class EdgeList, class Vertex >
0840     inline void remove_edge_and_property(
0841         Graph& g, EdgeList& el, Vertex v, boost::allow_parallel_edge_tag cat)
0842     {
0843         typedef typename Graph::global_edgelist_selector EdgeListS;
0844         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0845 
0846         typename EdgeList::iterator i = el.begin(), end = el.end();
0847         for (; i != end; ++i)
0848         {
0849             if ((*i).get_target() == v)
0850             {
0851                 // NOTE: Wihtout this skip, this loop will double-delete
0852                 // properties of loop edges. This solution is based on the
0853                 // observation that the incidence edges of a vertex with a loop
0854                 // are adjacent in the out edge list. This *may* actually hold
0855                 // for multisets also.
0856                 bool skip = (boost::next(i) != end
0857                     && i->get_iter() == boost::next(i)->get_iter());
0858                 g.m_edges.erase((*i).get_iter());
0859                 if (skip)
0860                     ++i;
0861             }
0862         }
0863         detail::erase_from_incidence_list(el, v, cat);
0864     }
0865     // O(log(E/V))
0866     template < class Graph, class EdgeList, class Vertex >
0867     inline void remove_edge_and_property(
0868         Graph& g, EdgeList& el, Vertex v, boost::disallow_parallel_edge_tag)
0869     {
0870         typedef typename Graph::global_edgelist_selector EdgeListS;
0871         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0872 
0873         typedef typename EdgeList::value_type StoredEdge;
0874         typename EdgeList::iterator i = el.find(StoredEdge(v)), end = el.end();
0875         if (i != end)
0876         {
0877             g.m_edges.erase((*i).get_iter());
0878             el.erase(i);
0879         }
0880     }
0881 
0882 } // namespace detail
0883 
0884 template < class Vertex, class EdgeProperty >
0885 struct list_edge // short name due to VC++ truncation and linker problems
0886 : public boost::detail::edge_base< boost::undirected_tag, Vertex >
0887 {
0888     typedef EdgeProperty property_type;
0889     typedef boost::detail::edge_base< boost::undirected_tag, Vertex > Base;
0890     list_edge(Vertex u, Vertex v, const EdgeProperty& p = EdgeProperty())
0891     : Base(u, v), m_property(p)
0892     {
0893     }
0894     EdgeProperty& get_property() { return m_property; }
0895     const EdgeProperty& get_property() const { return m_property; }
0896     // the following methods should never be used, but are needed
0897     // to make SGI MIPSpro C++ happy
0898     list_edge() {}
0899     bool operator==(const list_edge&) const { return false; }
0900     bool operator<(const list_edge&) const { return false; }
0901     EdgeProperty m_property;
0902 };
0903 
0904 template < class Config > struct undirected_graph_helper
0905 {
0906 
0907     typedef undir_adj_list_traversal_tag traversal_category;
0908 
0909     // Placement of these overloaded remove_edge() functions
0910     // inside the class avoids a VC++ bug.
0911 
0912     // O(E/V)
0913     inline void remove_edge(typename Config::edge_descriptor e)
0914     {
0915         typedef typename Config::global_edgelist_selector EdgeListS;
0916         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0917 
0918         typedef typename Config::OutEdgeList::value_type::property_type PType;
0919         detail::remove_undirected_edge_dispatch< PType >::apply(
0920             e, *this, *(PType*)e.get_property());
0921     }
0922     // O(E/V)
0923     inline void remove_edge(typename Config::out_edge_iterator iter)
0924     {
0925         this->remove_edge(*iter);
0926     }
0927 };
0928 
0929 // Had to make these non-members to avoid accidental instantiation
0930 // on SGI MIPSpro C++
0931 template < class C >
0932 inline typename C::InEdgeList& in_edge_list(
0933     undirected_graph_helper< C >&, typename C::vertex_descriptor v)
0934 {
0935     typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
0936     return sv->m_out_edges;
0937 }
0938 template < class C >
0939 inline const typename C::InEdgeList& in_edge_list(
0940     const undirected_graph_helper< C >&, typename C::vertex_descriptor v)
0941 {
0942     typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
0943     return sv->m_out_edges;
0944 }
0945 
0946 // O(E/V)
0947 template < class EdgeOrIter, class Config >
0948 inline void remove_edge(EdgeOrIter e, undirected_graph_helper< Config >& g_)
0949 {
0950     typedef typename Config::global_edgelist_selector EdgeListS;
0951     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0952 
0953     g_.remove_edge(e);
0954 }
0955 
0956 // O(E/V) or O(log(E/V))
0957 template < class Config >
0958 void remove_edge(typename Config::vertex_descriptor u,
0959     typename Config::vertex_descriptor v, undirected_graph_helper< Config >& g_)
0960 {
0961     typedef typename Config::global_edgelist_selector EdgeListS;
0962     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0963 
0964     typedef typename Config::graph_type graph_type;
0965     graph_type& g = static_cast< graph_type& >(g_);
0966     typedef typename Config::edge_parallel_category Cat;
0967     detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat());
0968     detail::erase_from_incidence_list(g.out_edge_list(v), u, Cat());
0969 }
0970 
0971 template < class Config, class Predicate >
0972 void remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
0973     undirected_graph_helper< Config >& g_)
0974 {
0975     typedef typename Config::global_edgelist_selector EdgeListS;
0976     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0977 
0978     typedef typename Config::graph_type graph_type;
0979     typedef typename Config::OutEdgeList::value_type::property_type PropT;
0980     graph_type& g = static_cast< graph_type& >(g_);
0981     typename Config::out_edge_iterator first, last;
0982     boost::tie(first, last) = out_edges(u, g);
0983     typedef typename Config::edge_parallel_category Cat;
0984     detail::undirected_remove_out_edge_if_dispatch< PropT >(
0985         g, first, last, g.out_edge_list(u), pred, Cat());
0986 }
0987 template < class Config, class Predicate >
0988 void remove_in_edge_if(typename Config::vertex_descriptor u, Predicate pred,
0989     undirected_graph_helper< Config >& g_)
0990 {
0991     typedef typename Config::global_edgelist_selector EdgeListS;
0992     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
0993 
0994     remove_out_edge_if(u, pred, g_);
0995 }
0996 
0997 // O(E/V * E) or O(log(E/V) * E)
0998 template < class Predicate, class Config >
0999 void remove_edge_if(Predicate pred, undirected_graph_helper< Config >& g_)
1000 {
1001     typedef typename Config::global_edgelist_selector EdgeListS;
1002     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1003 
1004     typedef typename Config::graph_type graph_type;
1005     graph_type& g = static_cast< graph_type& >(g_);
1006     typename Config::edge_iterator ei, ei_end, next;
1007     boost::tie(ei, ei_end) = edges(g);
1008     for (next = ei; ei != ei_end; ei = next)
1009     {
1010         ++next;
1011         if (pred(*ei))
1012             remove_edge(*ei, g);
1013     }
1014 }
1015 
1016 // O(1)
1017 template < class Config >
1018 inline std::pair< typename Config::edge_iterator,
1019     typename Config::edge_iterator >
1020 edges(const undirected_graph_helper< Config >& g_)
1021 {
1022     typedef typename Config::graph_type graph_type;
1023     typedef typename Config::edge_iterator edge_iterator;
1024     const graph_type& cg = static_cast< const graph_type& >(g_);
1025     graph_type& g = const_cast< graph_type& >(cg);
1026     return std::make_pair(
1027         edge_iterator(g.m_edges.begin()), edge_iterator(g.m_edges.end()));
1028 }
1029 // O(1)
1030 template < class Config >
1031 inline typename Config::edges_size_type num_edges(
1032     const undirected_graph_helper< Config >& g_)
1033 {
1034     typedef typename Config::graph_type graph_type;
1035     const graph_type& g = static_cast< const graph_type& >(g_);
1036     return g.m_edges.size();
1037 }
1038 // O(E/V * E/V)
1039 template < class Config >
1040 inline void clear_vertex(
1041     typename Config::vertex_descriptor u, undirected_graph_helper< Config >& g_)
1042 {
1043     typedef typename Config::global_edgelist_selector EdgeListS;
1044     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1045 
1046     typedef typename Config::graph_type graph_type;
1047     graph_type& g = static_cast< graph_type& >(g_);
1048     while (true)
1049     {
1050         typename Config::out_edge_iterator ei, ei_end;
1051         boost::tie(ei, ei_end) = out_edges(u, g);
1052         if (ei == ei_end)
1053             break;
1054         remove_edge(*ei, g);
1055     }
1056 }
1057 // O(1) for allow_parallel_edge_tag
1058 // O(log(E/V)) for disallow_parallel_edge_tag
1059 template < class Config >
1060 inline std::pair< typename Config::edge_descriptor, bool > add_edge(
1061     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
1062     const typename Config::edge_property_type& p,
1063     undirected_graph_helper< Config >& g_)
1064 {
1065     typedef typename Config::StoredEdge StoredEdge;
1066     typedef typename Config::edge_descriptor edge_descriptor;
1067     typedef typename Config::graph_type graph_type;
1068     graph_type& g = static_cast< graph_type& >(g_);
1069 
1070     bool inserted;
1071     typename Config::EdgeContainer::value_type e(u, v, p);
1072     typename Config::EdgeContainer::iterator p_iter
1073         = graph_detail::push(g.m_edges, e).first;
1074 
1075     typename Config::OutEdgeList::iterator i;
1076     boost::tie(i, inserted) = boost::graph_detail::push(
1077         g.out_edge_list(u), StoredEdge(v, p_iter, &g.m_edges));
1078     if (inserted)
1079     {
1080         boost::graph_detail::push(
1081             g.out_edge_list(v), StoredEdge(u, p_iter, &g.m_edges));
1082         return std::make_pair(
1083             edge_descriptor(u, v, &p_iter->get_property()), true);
1084     }
1085     else
1086     {
1087         g.m_edges.erase(p_iter);
1088         return std::make_pair(
1089             edge_descriptor(u, v, &i->get_iter()->get_property()), false);
1090     }
1091 }
1092 template < class Config >
1093 inline std::pair< typename Config::edge_descriptor, bool > add_edge(
1094     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
1095     undirected_graph_helper< Config >& g_)
1096 {
1097     typename Config::edge_property_type p;
1098     return add_edge(u, v, p, g_);
1099 }
1100 
1101 // O(1)
1102 template < class Config >
1103 inline typename Config::degree_size_type degree(
1104     typename Config::vertex_descriptor u,
1105     const undirected_graph_helper< Config >& g_)
1106 {
1107     typedef typename Config::graph_type Graph;
1108     const Graph& g = static_cast< const Graph& >(g_);
1109     return out_degree(u, g);
1110 }
1111 
1112 template < class Config >
1113 inline std::pair< typename Config::in_edge_iterator,
1114     typename Config::in_edge_iterator >
1115 in_edges(typename Config::vertex_descriptor u,
1116     const undirected_graph_helper< Config >& g_)
1117 {
1118     typedef typename Config::graph_type Graph;
1119     const Graph& cg = static_cast< const Graph& >(g_);
1120     Graph& g = const_cast< Graph& >(cg);
1121     typedef typename Config::in_edge_iterator in_edge_iterator;
1122     return std::make_pair(in_edge_iterator(g.out_edge_list(u).begin(), u),
1123         in_edge_iterator(g.out_edge_list(u).end(), u));
1124 }
1125 
1126 template < class Config >
1127 inline typename Config::degree_size_type in_degree(
1128     typename Config::vertex_descriptor u,
1129     const undirected_graph_helper< Config >& g_)
1130 {
1131     return degree(u, g_);
1132 }
1133 
1134 //=========================================================================
1135 // Bidirectional Graph Helper Class
1136 
1137 struct bidir_adj_list_traversal_tag : public virtual vertex_list_graph_tag,
1138                                       public virtual incidence_graph_tag,
1139                                       public virtual adjacency_graph_tag,
1140                                       public virtual edge_list_graph_tag,
1141                                       public virtual bidirectional_graph_tag
1142 {
1143 };
1144 
1145 template < class Config >
1146 struct bidirectional_graph_helper : public directed_edges_helper< Config >
1147 {
1148     typedef bidir_adj_list_traversal_tag traversal_category;
1149 };
1150 
1151 // Had to make these non-members to avoid accidental instantiation
1152 // on SGI MIPSpro C++
1153 template < class C >
1154 inline typename C::InEdgeList& in_edge_list(
1155     bidirectional_graph_helper< C >&, typename C::vertex_descriptor v)
1156 {
1157     typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
1158     return sv->m_in_edges;
1159 }
1160 template < class C >
1161 inline const typename C::InEdgeList& in_edge_list(
1162     const bidirectional_graph_helper< C >&, typename C::vertex_descriptor v)
1163 {
1164     typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
1165     return sv->m_in_edges;
1166 }
1167 
1168 template < class Predicate, class Config >
1169 inline void remove_edge_if(
1170     Predicate pred, bidirectional_graph_helper< Config >& g_)
1171 {
1172     typedef typename Config::global_edgelist_selector EdgeListS;
1173     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1174 
1175     typedef typename Config::graph_type graph_type;
1176     graph_type& g = static_cast< graph_type& >(g_);
1177     typename Config::edge_iterator ei, ei_end, next;
1178     boost::tie(ei, ei_end) = edges(g);
1179     for (next = ei; ei != ei_end; ei = next)
1180     {
1181         ++next;
1182         if (pred(*ei))
1183             remove_edge(*ei, g);
1184     }
1185 }
1186 
1187 template < class Config >
1188 inline std::pair< typename Config::in_edge_iterator,
1189     typename Config::in_edge_iterator >
1190 in_edges(typename Config::vertex_descriptor u,
1191     const bidirectional_graph_helper< Config >& g_)
1192 {
1193     typedef typename Config::graph_type graph_type;
1194     const graph_type& cg = static_cast< const graph_type& >(g_);
1195     graph_type& g = const_cast< graph_type& >(cg);
1196     typedef typename Config::in_edge_iterator in_edge_iterator;
1197     return std::make_pair(in_edge_iterator(in_edge_list(g, u).begin(), u),
1198         in_edge_iterator(in_edge_list(g, u).end(), u));
1199 }
1200 
1201 // O(1)
1202 template < class Config >
1203 inline std::pair< typename Config::edge_iterator,
1204     typename Config::edge_iterator >
1205 edges(const bidirectional_graph_helper< Config >& g_)
1206 {
1207     typedef typename Config::graph_type graph_type;
1208     typedef typename Config::edge_iterator edge_iterator;
1209     const graph_type& cg = static_cast< const graph_type& >(g_);
1210     graph_type& g = const_cast< graph_type& >(cg);
1211     return std::make_pair(
1212         edge_iterator(g.m_edges.begin()), edge_iterator(g.m_edges.end()));
1213 }
1214 
1215 //=========================================================================
1216 // Bidirectional Graph Helper Class (with edge properties)
1217 
1218 template < class Config >
1219 struct bidirectional_graph_helper_with_property
1220 : public bidirectional_graph_helper< Config >
1221 {
1222     typedef typename Config::graph_type graph_type;
1223     typedef typename Config::out_edge_iterator out_edge_iterator;
1224 
1225     std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist(
1226         typename Config::edge_descriptor e, const graph_type& g, void*)
1227     {
1228         return out_edges(source(e, g), g);
1229     }
1230 
1231     std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist(
1232         typename Config::edge_descriptor e, const graph_type& g, setS*)
1233     {
1234         return edge_range(source(e, g), target(e, g), g);
1235     }
1236 
1237     std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist(
1238         typename Config::edge_descriptor e, const graph_type& g, multisetS*)
1239     {
1240         return edge_range(source(e, g), target(e, g), g);
1241     }
1242 
1243     std::pair< out_edge_iterator, out_edge_iterator > get_parallel_edge_sublist(
1244         typename Config::edge_descriptor e, const graph_type& g, hash_setS*)
1245     {
1246         return edge_range(source(e, g), target(e, g), g);
1247     }
1248 
1249     // Placement of these overloaded remove_edge() functions
1250     // inside the class avoids a VC++ bug.
1251 
1252     // O(E/V) or O(log(E/V))
1253     void remove_edge(typename Config::edge_descriptor e)
1254     {
1255         typedef typename Config::global_edgelist_selector EdgeListS;
1256         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1257 
1258         graph_type& g = static_cast< graph_type& >(*this);
1259 
1260         typedef typename Config::edgelist_selector OutEdgeListS;
1261 
1262         std::pair< out_edge_iterator, out_edge_iterator > rng
1263             = get_parallel_edge_sublist(e, g, (OutEdgeListS*)(0));
1264         rng.first = std::find(rng.first, rng.second, e);
1265         BOOST_ASSERT(rng.first != rng.second);
1266         remove_edge(rng.first);
1267     }
1268 
1269     inline void remove_edge(typename Config::out_edge_iterator iter)
1270     {
1271         typedef typename Config::global_edgelist_selector EdgeListS;
1272         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1273 
1274         typedef typename Config::graph_type graph_type;
1275         graph_type& g = static_cast< graph_type& >(*this);
1276         typename Config::edge_descriptor e = *iter;
1277         typename Config::OutEdgeList& oel = g.out_edge_list(source(e, g));
1278         typename Config::InEdgeList& iel = in_edge_list(g, target(e, g));
1279         typedef typename Config::OutEdgeList::value_type::property_type PType;
1280         PType& p = *(PType*)e.get_property();
1281         detail::remove_directed_edge_dispatch(*iter, iel, p);
1282         g.m_edges.erase(iter.base()->get_iter());
1283         oel.erase(iter.base());
1284     }
1285 };
1286 
1287 // O(E/V) for allow_parallel_edge_tag
1288 // O(log(E/V)) for disallow_parallel_edge_tag
1289 template < class Config >
1290 inline void remove_edge(typename Config::vertex_descriptor u,
1291     typename Config::vertex_descriptor v,
1292     bidirectional_graph_helper_with_property< Config >& g_)
1293 {
1294     typedef typename Config::global_edgelist_selector EdgeListS;
1295     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1296 
1297     typedef typename Config::graph_type graph_type;
1298     graph_type& g = static_cast< graph_type& >(g_);
1299     typedef typename Config::edge_parallel_category Cat;
1300     detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat());
1301     detail::erase_from_incidence_list(in_edge_list(g, v), u, Cat());
1302 }
1303 
1304 // O(E/V) or O(log(E/V))
1305 template < class EdgeOrIter, class Config >
1306 inline void remove_edge(
1307     EdgeOrIter e, bidirectional_graph_helper_with_property< Config >& g_)
1308 {
1309     typedef typename Config::global_edgelist_selector EdgeListS;
1310     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1311 
1312     g_.remove_edge(e);
1313 }
1314 
1315 template < class Config, class Predicate >
1316 inline void remove_out_edge_if(typename Config::vertex_descriptor u,
1317     Predicate pred, bidirectional_graph_helper_with_property< Config >& g_)
1318 {
1319     typedef typename Config::global_edgelist_selector EdgeListS;
1320     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1321 
1322     typedef typename Config::graph_type graph_type;
1323     typedef typename Config::OutEdgeList::value_type::property_type PropT;
1324     graph_type& g = static_cast< graph_type& >(g_);
1325 
1326     typedef typename Config::EdgeIter EdgeIter;
1327     typedef std::vector< EdgeIter > Garbage;
1328     Garbage garbage;
1329 
1330     // First remove the edges from the targets' in-edge lists and
1331     // from the graph's edge set list.
1332     typename Config::out_edge_iterator out_i, out_end;
1333     for (boost::tie(out_i, out_end) = out_edges(u, g); out_i != out_end;
1334          ++out_i)
1335         if (pred(*out_i))
1336         {
1337             detail::remove_directed_edge_dispatch(*out_i,
1338                 in_edge_list(g, target(*out_i, g)),
1339                 *(PropT*)(*out_i).get_property());
1340             // Put in garbage to delete later. Will need the properties
1341             // for the remove_if of the out-edges.
1342             garbage.push_back((*out_i.base()).get_iter());
1343         }
1344 
1345     // Now remove the edges from this out-edge list.
1346     typename Config::out_edge_iterator first, last;
1347     boost::tie(first, last) = out_edges(u, g);
1348     typedef typename Config::edge_parallel_category Cat;
1349     detail::remove_directed_edge_if_dispatch(
1350         first, last, g.out_edge_list(u), pred, Cat());
1351 
1352     // Now delete the edge properties from the g.m_edges list
1353     for (typename Garbage::iterator i = garbage.begin(); i != garbage.end();
1354          ++i)
1355         g.m_edges.erase(*i);
1356 }
1357 template < class Config, class Predicate >
1358 inline void remove_in_edge_if(typename Config::vertex_descriptor v,
1359     Predicate pred, bidirectional_graph_helper_with_property< Config >& g_)
1360 {
1361     typedef typename Config::global_edgelist_selector EdgeListS;
1362     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1363 
1364     typedef typename Config::graph_type graph_type;
1365     typedef typename Config::OutEdgeList::value_type::property_type PropT;
1366     graph_type& g = static_cast< graph_type& >(g_);
1367 
1368     typedef typename Config::EdgeIter EdgeIter;
1369     typedef std::vector< EdgeIter > Garbage;
1370     Garbage garbage;
1371 
1372     // First remove the edges from the sources' out-edge lists and
1373     // from the graph's edge set list.
1374     typename Config::in_edge_iterator in_i, in_end;
1375     for (boost::tie(in_i, in_end) = in_edges(v, g); in_i != in_end; ++in_i)
1376         if (pred(*in_i))
1377         {
1378             typename Config::vertex_descriptor u = source(*in_i, g);
1379             detail::remove_directed_edge_dispatch(
1380                 *in_i, g.out_edge_list(u), *(PropT*)(*in_i).get_property());
1381             // Put in garbage to delete later. Will need the properties
1382             // for the remove_if of the out-edges.
1383             garbage.push_back((*in_i.base()).get_iter());
1384         }
1385     // Now remove the edges from this in-edge list.
1386     typename Config::in_edge_iterator first, last;
1387     boost::tie(first, last) = in_edges(v, g);
1388     typedef typename Config::edge_parallel_category Cat;
1389     detail::remove_directed_edge_if_dispatch(
1390         first, last, in_edge_list(g, v), pred, Cat());
1391 
1392     // Now delete the edge properties from the g.m_edges list
1393     for (typename Garbage::iterator i = garbage.begin(); i != garbage.end();
1394          ++i)
1395         g.m_edges.erase(*i);
1396 }
1397 
1398 // O(1)
1399 template < class Config >
1400 inline typename Config::edges_size_type num_edges(
1401     const bidirectional_graph_helper_with_property< Config >& g_)
1402 {
1403     typedef typename Config::graph_type graph_type;
1404     const graph_type& g = static_cast< const graph_type& >(g_);
1405     return g.m_edges.size();
1406 }
1407 // O(E/V * E/V) for allow_parallel_edge_tag
1408 // O(E/V * log(E/V)) for disallow_parallel_edge_tag
1409 template < class Config >
1410 inline void clear_vertex(typename Config::vertex_descriptor u,
1411     bidirectional_graph_helper_with_property< Config >& g_)
1412 {
1413     typedef typename Config::global_edgelist_selector EdgeListS;
1414     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1415 
1416     typedef typename Config::graph_type graph_type;
1417     typedef typename Config::edge_parallel_category Cat;
1418     graph_type& g = static_cast< graph_type& >(g_);
1419     typename Config::OutEdgeList& el = g.out_edge_list(u);
1420     typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end();
1421     for (; ei != ei_end; ++ei)
1422     {
1423         detail::erase_from_incidence_list(
1424             in_edge_list(g, (*ei).get_target()), u, Cat());
1425         g.m_edges.erase((*ei).get_iter());
1426     }
1427     typename Config::InEdgeList& in_el = in_edge_list(g, u);
1428     typename Config::InEdgeList::iterator in_ei = in_el.begin(),
1429                                           in_ei_end = in_el.end();
1430     for (; in_ei != in_ei_end; ++in_ei)
1431     {
1432         detail::erase_from_incidence_list(
1433             g.out_edge_list((*in_ei).get_target()), u, Cat());
1434         g.m_edges.erase((*in_ei).get_iter());
1435     }
1436     g.out_edge_list(u).clear();
1437     in_edge_list(g, u).clear();
1438 }
1439 
1440 template < class Config >
1441 inline void clear_out_edges(typename Config::vertex_descriptor u,
1442     bidirectional_graph_helper_with_property< Config >& g_)
1443 {
1444     typedef typename Config::global_edgelist_selector EdgeListS;
1445     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1446 
1447     typedef typename Config::graph_type graph_type;
1448     typedef typename Config::edge_parallel_category Cat;
1449     graph_type& g = static_cast< graph_type& >(g_);
1450     typename Config::OutEdgeList& el = g.out_edge_list(u);
1451     typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end();
1452     for (; ei != ei_end; ++ei)
1453     {
1454         detail::erase_from_incidence_list(
1455             in_edge_list(g, (*ei).get_target()), u, Cat());
1456         g.m_edges.erase((*ei).get_iter());
1457     }
1458     g.out_edge_list(u).clear();
1459 }
1460 
1461 template < class Config >
1462 inline void clear_in_edges(typename Config::vertex_descriptor u,
1463     bidirectional_graph_helper_with_property< Config >& g_)
1464 {
1465     typedef typename Config::global_edgelist_selector EdgeListS;
1466     BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
1467 
1468     typedef typename Config::graph_type graph_type;
1469     typedef typename Config::edge_parallel_category Cat;
1470     graph_type& g = static_cast< graph_type& >(g_);
1471     typename Config::InEdgeList& in_el = in_edge_list(g, u);
1472     typename Config::InEdgeList::iterator in_ei = in_el.begin(),
1473                                           in_ei_end = in_el.end();
1474     for (; in_ei != in_ei_end; ++in_ei)
1475     {
1476         detail::erase_from_incidence_list(
1477             g.out_edge_list((*in_ei).get_target()), u, Cat());
1478         g.m_edges.erase((*in_ei).get_iter());
1479     }
1480     in_edge_list(g, u).clear();
1481 }
1482 
1483 // O(1) for allow_parallel_edge_tag
1484 // O(log(E/V)) for disallow_parallel_edge_tag
1485 template < class Config >
1486 inline std::pair< typename Config::edge_descriptor, bool > add_edge(
1487     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
1488     const typename Config::edge_property_type& p,
1489     bidirectional_graph_helper_with_property< Config >& g_)
1490 {
1491     typedef typename Config::graph_type graph_type;
1492     graph_type& g = static_cast< graph_type& >(g_);
1493     typedef typename Config::edge_descriptor edge_descriptor;
1494     typedef typename Config::StoredEdge StoredEdge;
1495     bool inserted;
1496     typename Config::EdgeContainer::value_type e(u, v, p);
1497     typename Config::EdgeContainer::iterator p_iter
1498         = graph_detail::push(g.m_edges, e).first;
1499     typename Config::OutEdgeList::iterator i;
1500     boost::tie(i, inserted) = boost::graph_detail::push(
1501         g.out_edge_list(u), StoredEdge(v, p_iter, &g.m_edges));
1502     if (inserted)
1503     {
1504         boost::graph_detail::push(
1505             in_edge_list(g, v), StoredEdge(u, p_iter, &g.m_edges));
1506         return std::make_pair(edge_descriptor(u, v, &p_iter->m_property), true);
1507     }
1508     else
1509     {
1510         g.m_edges.erase(p_iter);
1511         return std::make_pair(
1512             edge_descriptor(u, v, &i->get_iter()->get_property()), false);
1513     }
1514 }
1515 
1516 template < class Config >
1517 inline std::pair< typename Config::edge_descriptor, bool > add_edge(
1518     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
1519     bidirectional_graph_helper_with_property< Config >& g_)
1520 {
1521     typename Config::edge_property_type p;
1522     return add_edge(u, v, p, g_);
1523 }
1524 // O(1)
1525 template < class Config >
1526 inline typename Config::degree_size_type degree(
1527     typename Config::vertex_descriptor u,
1528     const bidirectional_graph_helper_with_property< Config >& g_)
1529 {
1530     typedef typename Config::graph_type graph_type;
1531     const graph_type& g = static_cast< const graph_type& >(g_);
1532     return in_degree(u, g) + out_degree(u, g);
1533 }
1534 
1535 //=========================================================================
1536 // Adjacency List Helper Class
1537 
1538 template < class Config, class Base > struct adj_list_helper : public Base
1539 {
1540     typedef typename Config::graph_type AdjList;
1541     typedef typename Config::vertex_descriptor vertex_descriptor;
1542     typedef typename Config::edge_descriptor edge_descriptor;
1543     typedef typename Config::out_edge_iterator out_edge_iterator;
1544     typedef typename Config::in_edge_iterator in_edge_iterator;
1545     typedef typename Config::adjacency_iterator adjacency_iterator;
1546     typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator;
1547     typedef typename Config::vertex_iterator vertex_iterator;
1548     typedef typename Config::edge_iterator edge_iterator;
1549     typedef typename Config::directed_category directed_category;
1550     typedef typename Config::edge_parallel_category edge_parallel_category;
1551     typedef typename Config::vertices_size_type vertices_size_type;
1552     typedef typename Config::edges_size_type edges_size_type;
1553     typedef typename Config::degree_size_type degree_size_type;
1554     typedef typename Config::StoredEdge StoredEdge;
1555     typedef typename Config::vertex_property_type vertex_property_type;
1556     typedef typename Config::edge_property_type edge_property_type;
1557     typedef typename Config::graph_property_type graph_property_type;
1558 
1559     typedef typename Config::global_edgelist_selector global_edgelist_selector;
1560 
1561     typedef typename lookup_one_property< vertex_property_type,
1562         vertex_bundle_t >::type vertex_bundled;
1563     typedef
1564         typename lookup_one_property< edge_property_type, edge_bundle_t >::type
1565             edge_bundled;
1566     typedef typename lookup_one_property< graph_property_type,
1567         graph_bundle_t >::type graph_bundled;
1568 };
1569 
1570 template < class Config, class Base >
1571 inline std::pair< typename Config::adjacency_iterator,
1572     typename Config::adjacency_iterator >
1573 adjacent_vertices(typename Config::vertex_descriptor u,
1574     const adj_list_helper< Config, Base >& g_)
1575 {
1576     typedef typename Config::graph_type AdjList;
1577     const AdjList& cg = static_cast< const AdjList& >(g_);
1578     AdjList& g = const_cast< AdjList& >(cg);
1579     typedef typename Config::adjacency_iterator adjacency_iterator;
1580     typename Config::out_edge_iterator first, last;
1581     boost::tie(first, last) = out_edges(u, g);
1582     return std::make_pair(
1583         adjacency_iterator(first, &g), adjacency_iterator(last, &g));
1584 }
1585 template < class Config, class Base >
1586 inline std::pair< typename Config::inv_adjacency_iterator,
1587     typename Config::inv_adjacency_iterator >
1588 inv_adjacent_vertices(typename Config::vertex_descriptor u,
1589     const adj_list_helper< Config, Base >& g_)
1590 {
1591     typedef typename Config::graph_type AdjList;
1592     const AdjList& cg = static_cast< const AdjList& >(g_);
1593     AdjList& g = const_cast< AdjList& >(cg);
1594     typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator;
1595     typename Config::in_edge_iterator first, last;
1596     boost::tie(first, last) = in_edges(u, g);
1597     return std::make_pair(
1598         inv_adjacency_iterator(first, &g), inv_adjacency_iterator(last, &g));
1599 }
1600 template < class Config, class Base >
1601 inline std::pair< typename Config::out_edge_iterator,
1602     typename Config::out_edge_iterator >
1603 out_edges(typename Config::vertex_descriptor u,
1604     const adj_list_helper< Config, Base >& g_)
1605 {
1606     typedef typename Config::graph_type AdjList;
1607     typedef typename Config::out_edge_iterator out_edge_iterator;
1608     const AdjList& cg = static_cast< const AdjList& >(g_);
1609     AdjList& g = const_cast< AdjList& >(cg);
1610     return std::make_pair(out_edge_iterator(g.out_edge_list(u).begin(), u),
1611         out_edge_iterator(g.out_edge_list(u).end(), u));
1612 }
1613 template < class Config, class Base >
1614 inline std::pair< typename Config::vertex_iterator,
1615     typename Config::vertex_iterator >
1616 vertices(const adj_list_helper< Config, Base >& g_)
1617 {
1618     typedef typename Config::graph_type AdjList;
1619     const AdjList& cg = static_cast< const AdjList& >(g_);
1620     AdjList& g = const_cast< AdjList& >(cg);
1621     return std::make_pair(g.vertex_set().begin(), g.vertex_set().end());
1622 }
1623 template < class Config, class Base >
1624 inline typename Config::vertices_size_type num_vertices(
1625     const adj_list_helper< Config, Base >& g_)
1626 {
1627     typedef typename Config::graph_type AdjList;
1628     const AdjList& g = static_cast< const AdjList& >(g_);
1629     return g.vertex_set().size();
1630 }
1631 template < class Config, class Base >
1632 inline typename Config::degree_size_type out_degree(
1633     typename Config::vertex_descriptor u,
1634     const adj_list_helper< Config, Base >& g_)
1635 {
1636     typedef typename Config::graph_type AdjList;
1637     const AdjList& g = static_cast< const AdjList& >(g_);
1638     return g.out_edge_list(u).size();
1639 }
1640 template < class Config, class Base >
1641 inline std::pair< typename Config::edge_descriptor, bool > edge(
1642     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
1643     const adj_list_helper< Config, Base >& g_)
1644 {
1645     typedef typename Config::graph_type Graph;
1646     typedef typename Config::StoredEdge StoredEdge;
1647     const Graph& cg = static_cast< const Graph& >(g_);
1648     const typename Config::OutEdgeList& el = cg.out_edge_list(u);
1649     typename Config::OutEdgeList::const_iterator it
1650         = graph_detail::find(el, StoredEdge(v));
1651     return std::make_pair(typename Config::edge_descriptor(u, v,
1652                               (it == el.end() ? 0 : &(*it).get_property())),
1653         (it != el.end()));
1654 }
1655 
1656 template < class Config, class Base >
1657 inline std::pair< typename Config::out_edge_iterator,
1658     typename Config::out_edge_iterator >
1659 edge_range(typename Config::vertex_descriptor u,
1660     typename Config::vertex_descriptor v,
1661     const adj_list_helper< Config, Base >& g_)
1662 {
1663     typedef typename Config::graph_type Graph;
1664     typedef typename Config::StoredEdge StoredEdge;
1665     const Graph& cg = static_cast< const Graph& >(g_);
1666     Graph& g = const_cast< Graph& >(cg);
1667     typedef typename Config::out_edge_iterator out_edge_iterator;
1668     typename Config::OutEdgeList& el = g.out_edge_list(u);
1669     typename Config::OutEdgeList::iterator first, last;
1670     typename Config::EdgeContainer fake_edge_container;
1671     boost::tie(first, last) = graph_detail::equal_range(el, StoredEdge(v));
1672     return std::make_pair(
1673         out_edge_iterator(first, u), out_edge_iterator(last, u));
1674 }
1675 
1676 template < class Config >
1677 inline typename Config::degree_size_type in_degree(
1678     typename Config::vertex_descriptor u,
1679     const directed_edges_helper< Config >& g_)
1680 {
1681     typedef typename Config::graph_type Graph;
1682     const Graph& cg = static_cast< const Graph& >(g_);
1683     Graph& g = const_cast< Graph& >(cg);
1684     return in_edge_list(g, u).size();
1685 }
1686 
1687 namespace detail
1688 {
1689     template < class Config, class Base, class Property >
1690     inline typename boost::property_map< typename Config::graph_type,
1691         Property >::type
1692     get_dispatch(
1693         adj_list_helper< Config, Base >&, Property p, boost::edge_property_tag)
1694     {
1695         typedef typename Config::graph_type Graph;
1696         typedef typename boost::property_map< Graph, Property >::type PA;
1697         return PA(p);
1698     }
1699     template < class Config, class Base, class Property >
1700     inline typename boost::property_map< typename Config::graph_type,
1701         Property >::const_type
1702     get_dispatch(const adj_list_helper< Config, Base >&, Property p,
1703         boost::edge_property_tag)
1704     {
1705         typedef typename Config::graph_type Graph;
1706         typedef typename boost::property_map< Graph, Property >::const_type PA;
1707         return PA(p);
1708     }
1709 
1710     template < class Config, class Base, class Property >
1711     inline typename boost::property_map< typename Config::graph_type,
1712         Property >::type
1713     get_dispatch(adj_list_helper< Config, Base >& g, Property p,
1714         boost::vertex_property_tag)
1715     {
1716         typedef typename Config::graph_type Graph;
1717         typedef typename boost::property_map< Graph, Property >::type PA;
1718         return PA(&static_cast< Graph& >(g), p);
1719     }
1720     template < class Config, class Base, class Property >
1721     inline typename boost::property_map< typename Config::graph_type,
1722         Property >::const_type
1723     get_dispatch(const adj_list_helper< Config, Base >& g, Property p,
1724         boost::vertex_property_tag)
1725     {
1726         typedef typename Config::graph_type Graph;
1727         typedef typename boost::property_map< Graph, Property >::const_type PA;
1728         const Graph& cg = static_cast< const Graph& >(g);
1729         return PA(&cg, p);
1730     }
1731 
1732 } // namespace detail
1733 
1734 // Implementation of the PropertyGraph interface
1735 template < class Config, class Base, class Property >
1736 inline
1737     typename boost::property_map< typename Config::graph_type, Property >::type
1738     get(Property p, adj_list_helper< Config, Base >& g)
1739 {
1740     typedef typename detail::property_kind_from_graph<
1741         adj_list_helper< Config, Base >, Property >::type Kind;
1742     return detail::get_dispatch(g, p, Kind());
1743 }
1744 template < class Config, class Base, class Property >
1745 inline typename boost::property_map< typename Config::graph_type,
1746     Property >::const_type
1747 get(Property p, const adj_list_helper< Config, Base >& g)
1748 {
1749     typedef typename detail::property_kind_from_graph<
1750         adj_list_helper< Config, Base >, Property >::type Kind;
1751     return detail::get_dispatch(g, p, Kind());
1752 }
1753 
1754 template < class Config, class Base, class Property, class Key >
1755 inline typename boost::property_traits< typename boost::property_map<
1756     typename Config::graph_type, Property >::type >::reference
1757 get(Property p, adj_list_helper< Config, Base >& g, const Key& key)
1758 {
1759     return get(get(p, g), key);
1760 }
1761 
1762 template < class Config, class Base, class Property, class Key >
1763 inline typename boost::property_traits< typename boost::property_map<
1764     typename Config::graph_type, Property >::const_type >::reference
1765 get(Property p, const adj_list_helper< Config, Base >& g, const Key& key)
1766 {
1767     return get(get(p, g), key);
1768 }
1769 
1770 template < class Config, class Base, class Property, class Key, class Value >
1771 inline void put(Property p, adj_list_helper< Config, Base >& g, const Key& key,
1772     const Value& value)
1773 {
1774     typedef typename Config::graph_type Graph;
1775     typedef typename boost::property_map< Graph, Property >::type Map;
1776     Map pmap = get(p, static_cast< Graph& >(g));
1777     put(pmap, key, value);
1778 }
1779 
1780 //=========================================================================
1781 // Generalize Adjacency List Implementation
1782 
1783 struct adj_list_tag
1784 {
1785 };
1786 
1787 template < class Derived, class Config, class Base >
1788 class adj_list_impl : public adj_list_helper< Config, Base >
1789 {
1790     typedef typename Config::OutEdgeList OutEdgeList;
1791     typedef typename Config::InEdgeList InEdgeList;
1792     typedef typename Config::StoredVertexList StoredVertexList;
1793 
1794 public:
1795     typedef typename Config::stored_vertex stored_vertex;
1796     typedef typename Config::EdgeContainer EdgeContainer;
1797     typedef typename Config::vertex_descriptor vertex_descriptor;
1798     typedef typename Config::edge_descriptor edge_descriptor;
1799     typedef typename Config::vertex_iterator vertex_iterator;
1800     typedef typename Config::edge_iterator edge_iterator;
1801     typedef typename Config::edge_parallel_category edge_parallel_category;
1802     typedef typename Config::vertices_size_type vertices_size_type;
1803     typedef typename Config::edges_size_type edges_size_type;
1804     typedef typename Config::degree_size_type degree_size_type;
1805     typedef typename Config::edge_property_type edge_property_type;
1806     typedef adj_list_tag graph_tag;
1807 
1808     static vertex_descriptor null_vertex() { return 0; }
1809 
1810     inline adj_list_impl() {}
1811 
1812     inline adj_list_impl(const adj_list_impl& x) { copy_impl(x); }
1813     inline adj_list_impl& operator=(const adj_list_impl& x)
1814     {
1815         this->clear();
1816         copy_impl(x);
1817         return *this;
1818     }
1819     inline void clear()
1820     {
1821         for (typename StoredVertexList::iterator i = m_vertices.begin();
1822              i != m_vertices.end(); ++i)
1823             delete (stored_vertex*)*i;
1824         m_vertices.clear();
1825         m_edges.clear();
1826     }
1827     inline adj_list_impl(vertices_size_type num_vertices)
1828     {
1829         for (vertices_size_type i = 0; i < num_vertices; ++i)
1830             add_vertex(static_cast< Derived& >(*this));
1831     }
1832     template < class EdgeIterator >
1833     inline adj_list_impl(
1834         vertices_size_type num_vertices, EdgeIterator first, EdgeIterator last)
1835     {
1836         vertex_descriptor* v = new vertex_descriptor[num_vertices];
1837         for (vertices_size_type i = 0; i < num_vertices; ++i)
1838             v[i] = add_vertex(static_cast< Derived& >(*this));
1839 
1840         while (first != last)
1841         {
1842             add_edge(v[(*first).first], v[(*first).second], *this);
1843             ++first;
1844         }
1845         delete[] v;
1846     }
1847     template < class EdgeIterator, class EdgePropertyIterator >
1848     inline adj_list_impl(vertices_size_type num_vertices, EdgeIterator first,
1849         EdgeIterator last, EdgePropertyIterator ep_iter)
1850     {
1851         vertex_descriptor* v = new vertex_descriptor[num_vertices];
1852         for (vertices_size_type i = 0; i < num_vertices; ++i)
1853             v[i] = add_vertex(static_cast< Derived& >(*this));
1854 
1855         while (first != last)
1856         {
1857             add_edge(v[(*first).first], v[(*first).second], *ep_iter, *this);
1858             ++first;
1859             ++ep_iter;
1860         }
1861         delete[] v;
1862     }
1863     ~adj_list_impl()
1864     {
1865         for (typename StoredVertexList::iterator i = m_vertices.begin();
1866              i != m_vertices.end(); ++i)
1867             delete (stored_vertex*)*i;
1868     }
1869     //    protected:
1870     inline OutEdgeList& out_edge_list(vertex_descriptor v)
1871     {
1872         stored_vertex* sv = (stored_vertex*)v;
1873         return sv->m_out_edges;
1874     }
1875     inline const OutEdgeList& out_edge_list(vertex_descriptor v) const
1876     {
1877         stored_vertex* sv = (stored_vertex*)v;
1878         return sv->m_out_edges;
1879     }
1880     inline StoredVertexList& vertex_set() { return m_vertices; }
1881     inline const StoredVertexList& vertex_set() const { return m_vertices; }
1882 
1883     inline void copy_impl(const adj_list_impl& x_)
1884     {
1885         const Derived& x = static_cast< const Derived& >(x_);
1886 
1887         // Would be better to have a constant time way to get from
1888         // vertices in x to the corresponding vertices in *this.
1889         std::map< stored_vertex*, stored_vertex* > vertex_map;
1890 
1891         // Copy the stored vertex objects by adding each vertex
1892         // and copying its property object.
1893         vertex_iterator vi, vi_end;
1894         for (boost::tie(vi, vi_end) = vertices(x); vi != vi_end; ++vi)
1895         {
1896             stored_vertex* v = (stored_vertex*)add_vertex(*this);
1897             v->m_property = ((stored_vertex*)*vi)->m_property;
1898             vertex_map[(stored_vertex*)*vi] = v;
1899         }
1900         // Copy the edges by adding each edge and copying its
1901         // property object.
1902         edge_iterator ei, ei_end;
1903         for (boost::tie(ei, ei_end) = edges(x); ei != ei_end; ++ei)
1904         {
1905             edge_descriptor e;
1906             bool inserted;
1907             vertex_descriptor s = source(*ei, x), t = target(*ei, x);
1908             boost::tie(e, inserted) = add_edge(vertex_map[(stored_vertex*)s],
1909                 vertex_map[(stored_vertex*)t], *this);
1910             *((edge_property_type*)e.m_eproperty)
1911                 = *((edge_property_type*)(*ei).m_eproperty);
1912         }
1913     }
1914 
1915     typename Config::EdgeContainer m_edges;
1916     StoredVertexList m_vertices;
1917 };
1918 
1919 // O(1)
1920 template < class Derived, class Config, class Base >
1921 inline typename Config::vertex_descriptor add_vertex(
1922     adj_list_impl< Derived, Config, Base >& g_)
1923 {
1924     Derived& g = static_cast< Derived& >(g_);
1925     typedef typename Config::stored_vertex stored_vertex;
1926     stored_vertex* v = new stored_vertex;
1927     typename Config::StoredVertexList::iterator pos;
1928     bool inserted;
1929     boost::tie(pos, inserted) = boost::graph_detail::push(g.m_vertices, v);
1930     v->m_position = pos;
1931     g.added_vertex(v);
1932     return v;
1933 }
1934 // O(1)
1935 template < class Derived, class Config, class Base >
1936 inline typename Config::vertex_descriptor add_vertex(
1937     const typename Config::vertex_property_type& p,
1938     adj_list_impl< Derived, Config, Base >& g_)
1939 {
1940     typedef typename Config::vertex_descriptor vertex_descriptor;
1941     Derived& g = static_cast< Derived& >(g_);
1942     if (optional< vertex_descriptor > v
1943         = g.vertex_by_property(get_property_value(p, vertex_bundle)))
1944         return *v;
1945 
1946     typedef typename Config::stored_vertex stored_vertex;
1947     stored_vertex* v = new stored_vertex(p);
1948     typename Config::StoredVertexList::iterator pos;
1949     bool inserted;
1950     boost::tie(pos, inserted) = boost::graph_detail::push(g.m_vertices, v);
1951     v->m_position = pos;
1952     g.added_vertex(v);
1953     return v;
1954 }
1955 // O(1)
1956 template < class Derived, class Config, class Base >
1957 inline void remove_vertex(typename Config::vertex_descriptor u,
1958     adj_list_impl< Derived, Config, Base >& g_)
1959 {
1960     typedef typename Config::stored_vertex stored_vertex;
1961     Derived& g = static_cast< Derived& >(g_);
1962     g.removing_vertex(
1963         u, boost::graph_detail::iterator_stability(g_.m_vertices));
1964     stored_vertex* su = (stored_vertex*)u;
1965     g.m_vertices.erase(su->m_position);
1966     delete su;
1967 }
1968 // O(V)
1969 template < class Derived, class Config, class Base >
1970 inline typename Config::vertex_descriptor vertex(
1971     typename Config::vertices_size_type n,
1972     const adj_list_impl< Derived, Config, Base >& g_)
1973 {
1974     const Derived& g = static_cast< const Derived& >(g_);
1975     typename Config::vertex_iterator i = vertices(g).first;
1976     while (n--)
1977         ++i; // std::advance(i, n); (not VC++ portable)
1978     return *i;
1979 }
1980 
1981 //=========================================================================
1982 // Vector-Backbone Adjacency List Implementation
1983 
1984 namespace detail
1985 {
1986 
1987     template < class Graph, class vertex_descriptor >
1988     inline void remove_vertex_dispatch(
1989         Graph& g, vertex_descriptor u, boost::directed_tag)
1990     {
1991         typedef typename Graph::edge_parallel_category edge_parallel_category;
1992         g.m_vertices.erase(g.m_vertices.begin() + u);
1993         vertex_descriptor V = num_vertices(g);
1994         if (u != V)
1995         {
1996             for (vertex_descriptor v = 0; v < V; ++v)
1997                 reindex_edge_list(
1998                     g.out_edge_list(v), u, edge_parallel_category());
1999         }
2000     }
2001 
2002     template < class Graph, class vertex_descriptor >
2003     inline void remove_vertex_dispatch(
2004         Graph& g, vertex_descriptor u, boost::undirected_tag)
2005     {
2006         typedef typename Graph::global_edgelist_selector EdgeListS;
2007         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
2008 
2009         typedef typename Graph::edge_parallel_category edge_parallel_category;
2010         g.m_vertices.erase(g.m_vertices.begin() + u);
2011         vertex_descriptor V = num_vertices(g);
2012         for (vertex_descriptor v = 0; v < V; ++v)
2013             reindex_edge_list(g.out_edge_list(v), u, edge_parallel_category());
2014         typedef typename Graph::EdgeContainer Container;
2015         typedef typename Container::iterator Iter;
2016         Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end();
2017         for (; ei != ei_end; ++ei)
2018         {
2019             if (ei->m_source > u)
2020                 --ei->m_source;
2021             if (ei->m_target > u)
2022                 --ei->m_target;
2023         }
2024     }
2025     template < class Graph, class vertex_descriptor >
2026     inline void remove_vertex_dispatch(
2027         Graph& g, vertex_descriptor u, boost::bidirectional_tag)
2028     {
2029         typedef typename Graph::global_edgelist_selector EdgeListS;
2030         BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
2031 
2032         typedef typename Graph::edge_parallel_category edge_parallel_category;
2033         g.m_vertices.erase(g.m_vertices.begin() + u);
2034         vertex_descriptor V = num_vertices(g);
2035         vertex_descriptor v;
2036         if (u != V)
2037         {
2038             for (v = 0; v < V; ++v)
2039                 reindex_edge_list(
2040                     g.out_edge_list(v), u, edge_parallel_category());
2041             for (v = 0; v < V; ++v)
2042                 reindex_edge_list(
2043                     in_edge_list(g, v), u, edge_parallel_category());
2044 
2045             typedef typename Graph::EdgeContainer Container;
2046             typedef typename Container::iterator Iter;
2047             Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end();
2048             for (; ei != ei_end; ++ei)
2049             {
2050                 if (ei->m_source > u)
2051                     --ei->m_source;
2052                 if (ei->m_target > u)
2053                     --ei->m_target;
2054             }
2055         }
2056     }
2057 
2058     template < class EdgeList, class vertex_descriptor >
2059     inline void reindex_edge_list(
2060         EdgeList& el, vertex_descriptor u, boost::allow_parallel_edge_tag)
2061     {
2062         typename EdgeList::iterator ei = el.begin(), e_end = el.end();
2063         for (; ei != e_end; ++ei)
2064             if ((*ei).get_target() > u)
2065                 --(*ei).get_target();
2066     }
2067 
2068     template < class EdgeList, class vertex_descriptor >
2069     inline void reindex_edge_list(
2070         EdgeList& el, vertex_descriptor u, boost::disallow_parallel_edge_tag)
2071     {
2072         typename EdgeList::iterator ei = el.begin(), e_end = el.end();
2073         while (ei != e_end)
2074         {
2075             if (ei->get_target() > u)
2076             {
2077                 typename EdgeList::value_type ce = *ei;
2078                 ++ei;
2079                 el.erase(ce);
2080                 --ce.get_target();
2081                 el.insert(ce);
2082             }
2083             else {
2084                 ++ei;
2085             }
2086         }
2087     }
2088 } // namespace detail
2089 
2090 struct vec_adj_list_tag
2091 {
2092 };
2093 
2094 template < class Graph, class Config, class Base >
2095 class vec_adj_list_impl : public adj_list_helper< Config, Base >
2096 {
2097     typedef typename Config::OutEdgeList OutEdgeList;
2098     typedef typename Config::InEdgeList InEdgeList;
2099     typedef typename Config::StoredVertexList StoredVertexList;
2100 
2101 public:
2102     typedef typename Config::vertex_descriptor vertex_descriptor;
2103     typedef typename Config::edge_descriptor edge_descriptor;
2104     typedef typename Config::out_edge_iterator out_edge_iterator;
2105     typedef typename Config::edge_iterator edge_iterator;
2106     typedef typename Config::directed_category directed_category;
2107     typedef typename Config::vertices_size_type vertices_size_type;
2108     typedef typename Config::edges_size_type edges_size_type;
2109     typedef typename Config::degree_size_type degree_size_type;
2110     typedef typename Config::StoredEdge StoredEdge;
2111     typedef typename Config::stored_vertex stored_vertex;
2112     typedef typename Config::EdgeContainer EdgeContainer;
2113     typedef typename Config::edge_property_type edge_property_type;
2114     typedef vec_adj_list_tag graph_tag;
2115 
2116     static vertex_descriptor null_vertex()
2117     {
2118         return (std::numeric_limits< vertex_descriptor >::max)();
2119     }
2120 
2121     inline vec_adj_list_impl() {}
2122 
2123     inline vec_adj_list_impl(const vec_adj_list_impl& x) { copy_impl(x); }
2124     inline vec_adj_list_impl& operator=(const vec_adj_list_impl& x)
2125     {
2126         this->clear();
2127         copy_impl(x);
2128         return *this;
2129     }
2130     inline void clear()
2131     {
2132         m_vertices.clear();
2133         m_edges.clear();
2134     }
2135 
2136     inline vec_adj_list_impl(vertices_size_type _num_vertices)
2137     : m_vertices(_num_vertices)
2138     {
2139     }
2140 
2141     template < class EdgeIterator >
2142     inline vec_adj_list_impl(
2143         vertices_size_type num_vertices, EdgeIterator first, EdgeIterator last)
2144     : m_vertices(num_vertices)
2145     {
2146         while (first != last)
2147         {
2148             add_edge(
2149                 (*first).first, (*first).second, static_cast< Graph& >(*this));
2150             ++first;
2151         }
2152     }
2153     template < class EdgeIterator, class EdgePropertyIterator >
2154     inline vec_adj_list_impl(vertices_size_type num_vertices,
2155         EdgeIterator first, EdgeIterator last, EdgePropertyIterator ep_iter)
2156     : m_vertices(num_vertices)
2157     {
2158         while (first != last)
2159         {
2160             add_edge((*first).first, (*first).second, *ep_iter,
2161                 static_cast< Graph& >(*this));
2162             ++first;
2163             ++ep_iter;
2164         }
2165     }
2166 
2167     //    protected:
2168     inline boost::integer_range< vertex_descriptor > vertex_set() const
2169     {
2170         return boost::integer_range< vertex_descriptor >(0, m_vertices.size());
2171     }
2172     inline OutEdgeList& out_edge_list(vertex_descriptor v)
2173     {
2174         return m_vertices[v].m_out_edges;
2175     }
2176     inline const OutEdgeList& out_edge_list(vertex_descriptor v) const
2177     {
2178         return m_vertices[v].m_out_edges;
2179     }
2180     inline void copy_impl(const vec_adj_list_impl& x_)
2181     {
2182         const Graph& x = static_cast< const Graph& >(x_);
2183         // Copy the stored vertex objects by adding each vertex
2184         // and copying its property object.
2185         for (vertices_size_type i = 0; i < num_vertices(x); ++i)
2186         {
2187             vertex_descriptor v = add_vertex(*this);
2188             m_vertices[v].m_property = x.m_vertices[i].m_property;
2189         }
2190         // Copy the edges by adding each edge and copying its
2191         // property object.
2192         edge_iterator ei, ei_end;
2193         for (boost::tie(ei, ei_end) = edges(x); ei != ei_end; ++ei)
2194         {
2195             edge_descriptor e;
2196             bool inserted;
2197             boost::tie(e, inserted)
2198                 = add_edge(source(*ei, x), target(*ei, x), *this);
2199             *((edge_property_type*)e.m_eproperty)
2200                 = *((edge_property_type*)(*ei).m_eproperty);
2201         }
2202     }
2203     typename Config::EdgeContainer m_edges;
2204     StoredVertexList m_vertices;
2205 };
2206 // Had to make these non-members to avoid accidental instantiation
2207 // on SGI MIPSpro C++
2208 template < class G, class C, class B >
2209 inline typename C::InEdgeList& in_edge_list(
2210     vec_adj_list_impl< G, C, B >& g, typename C::vertex_descriptor v)
2211 {
2212     return g.m_vertices[v].m_in_edges;
2213 }
2214 template < class G, class C, class B >
2215 inline const typename C::InEdgeList& in_edge_list(
2216     const vec_adj_list_impl< G, C, B >& g, typename C::vertex_descriptor v)
2217 {
2218     return g.m_vertices[v].m_in_edges;
2219 }
2220 
2221 // O(1)
2222 template < class Graph, class Config, class Base >
2223 inline typename Config::vertex_descriptor add_vertex(
2224     vec_adj_list_impl< Graph, Config, Base >& g_)
2225 {
2226     Graph& g = static_cast< Graph& >(g_);
2227     g.m_vertices.resize(g.m_vertices.size() + 1);
2228     g.added_vertex(g.m_vertices.size() - 1);
2229     return g.m_vertices.size() - 1;
2230 }
2231 
2232 template < class Graph, class Config, class Base >
2233 inline typename Config::vertex_descriptor add_vertex(
2234     const typename Config::vertex_property_type& p,
2235     vec_adj_list_impl< Graph, Config, Base >& g_)
2236 {
2237     typedef typename Config::vertex_descriptor vertex_descriptor;
2238     Graph& g = static_cast< Graph& >(g_);
2239     if (optional< vertex_descriptor > v
2240         = g.vertex_by_property(get_property_value(p, vertex_bundle)))
2241         return *v;
2242     typedef typename Config::stored_vertex stored_vertex;
2243     g.m_vertices.push_back(stored_vertex(p));
2244     g.added_vertex(g.m_vertices.size() - 1);
2245     return g.m_vertices.size() - 1;
2246 }
2247 
2248 // Here we override the directed_graph_helper add_edge() function
2249 // so that the number of vertices is automatically changed if
2250 // either u or v is greater than the number of vertices.
2251 template < class Graph, class Config, class Base >
2252 inline std::pair< typename Config::edge_descriptor, bool > add_edge(
2253     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
2254     const typename Config::edge_property_type& p,
2255     vec_adj_list_impl< Graph, Config, Base >& g_)
2256 {
2257     BOOST_USING_STD_MAX();
2258     typename Config::vertex_descriptor x
2259         = max BOOST_PREVENT_MACRO_SUBSTITUTION(u, v);
2260     if (x >= num_vertices(g_))
2261         g_.m_vertices.resize(x + 1);
2262     adj_list_helper< Config, Base >& g = g_;
2263     return add_edge(u, v, p, g);
2264 }
2265 template < class Graph, class Config, class Base >
2266 inline std::pair< typename Config::edge_descriptor, bool > add_edge(
2267     typename Config::vertex_descriptor u, typename Config::vertex_descriptor v,
2268     vec_adj_list_impl< Graph, Config, Base >& g_)
2269 {
2270     typename Config::edge_property_type p;
2271     return add_edge(u, v, p, g_);
2272 }
2273 
2274 // O(V + E)
2275 template < class Graph, class Config, class Base >
2276 inline void remove_vertex(typename Config::vertex_descriptor v,
2277     vec_adj_list_impl< Graph, Config, Base >& g_)
2278 {
2279     typedef typename Config::directed_category Cat;
2280     Graph& g = static_cast< Graph& >(g_);
2281     g.removing_vertex(
2282         v, boost::graph_detail::iterator_stability(g_.m_vertices));
2283     detail::remove_vertex_dispatch(g, v, Cat());
2284 }
2285 // O(1)
2286 template < class Graph, class Config, class Base >
2287 inline typename Config::vertex_descriptor vertex(
2288     typename Config::vertices_size_type n,
2289     const vec_adj_list_impl< Graph, Config, Base >&)
2290 {
2291     return n;
2292 }
2293 
2294 namespace detail
2295 {
2296 
2297     //=========================================================================
2298     // Adjacency List Generator
2299 
2300     template < class Graph, class VertexListS, class OutEdgeListS,
2301         class DirectedS, class VertexProperty, class EdgeProperty,
2302         class GraphProperty, class EdgeListS >
2303     struct adj_list_gen
2304     {
2305         typedef typename detail::is_random_access< VertexListS >::type
2306             is_rand_access;
2307         typedef typename has_property< EdgeProperty >::type has_edge_property;
2308         typedef typename DirectedS::is_directed_t DirectedT;
2309         typedef typename DirectedS::is_bidir_t BidirectionalT;
2310 
2311         struct config
2312         {
2313             typedef OutEdgeListS edgelist_selector;
2314             typedef EdgeListS global_edgelist_selector;
2315 
2316             typedef Graph graph_type;
2317             typedef EdgeProperty edge_property_type;
2318             typedef VertexProperty vertex_property_type;
2319             typedef GraphProperty graph_property_type;
2320             typedef std::size_t vertices_size_type;
2321 
2322             typedef adjacency_list_traits< OutEdgeListS, VertexListS,
2323                 DirectedS >
2324                 Traits;
2325 
2326             typedef typename Traits::directed_category directed_category;
2327             typedef
2328                 typename Traits::edge_parallel_category edge_parallel_category;
2329             typedef typename Traits::vertex_descriptor vertex_descriptor;
2330             typedef typename Traits::edge_descriptor edge_descriptor;
2331 
2332             typedef void* vertex_ptr;
2333 
2334             // need to reorganize this to avoid instantiating stuff
2335             // that doesn't get used -JGS
2336 
2337             // VertexList and vertex_iterator
2338             typedef typename container_gen< VertexListS, vertex_ptr >::type
2339                 SeqVertexList;
2340             typedef boost::integer_range< vertex_descriptor > RandVertexList;
2341             typedef typename mpl::if_< is_rand_access, RandVertexList,
2342                 SeqVertexList >::type VertexList;
2343 
2344             typedef typename VertexList::iterator vertex_iterator;
2345 
2346             // EdgeContainer and StoredEdge
2347 
2348             typedef typename container_gen< EdgeListS,
2349                 list_edge< vertex_descriptor, EdgeProperty > >::type
2350                 EdgeContainer;
2351 
2352             typedef typename mpl::and_< DirectedT,
2353                 typename mpl::not_< BidirectionalT >::type >::type
2354                 on_edge_storage;
2355 
2356             typedef typename mpl::if_< on_edge_storage, std::size_t,
2357                 typename EdgeContainer::size_type >::type edges_size_type;
2358 
2359             typedef typename EdgeContainer::iterator EdgeIter;
2360 
2361             typedef
2362                 typename detail::is_random_access< EdgeListS >::type is_edge_ra;
2363 
2364             typedef typename mpl::if_< on_edge_storage,
2365                 stored_edge_property< vertex_descriptor, EdgeProperty >,
2366                 typename mpl::if_< is_edge_ra,
2367                     stored_ra_edge_iter< vertex_descriptor, EdgeContainer,
2368                         EdgeProperty >,
2369                     stored_edge_iter< vertex_descriptor, EdgeIter,
2370                         EdgeProperty > >::type >::type StoredEdge;
2371 
2372             // Adjacency Types
2373 
2374             typedef typename container_gen< OutEdgeListS, StoredEdge >::type
2375                 OutEdgeList;
2376             typedef typename OutEdgeList::size_type degree_size_type;
2377             typedef typename OutEdgeList::iterator OutEdgeIter;
2378 
2379             typedef std::iterator_traits< OutEdgeIter >
2380                 OutEdgeIterTraits;
2381             typedef
2382                 typename OutEdgeIterTraits::iterator_category OutEdgeIterCat;
2383             typedef typename OutEdgeIterTraits::difference_type OutEdgeIterDiff;
2384 
2385             typedef out_edge_iter< OutEdgeIter, vertex_descriptor,
2386                 edge_descriptor, OutEdgeIterDiff >
2387                 out_edge_iterator;
2388 
2389             typedef typename adjacency_iterator_generator< graph_type,
2390                 vertex_descriptor, out_edge_iterator >::type adjacency_iterator;
2391 
2392             typedef OutEdgeList InEdgeList;
2393             typedef OutEdgeIter InEdgeIter;
2394             typedef OutEdgeIterCat InEdgeIterCat;
2395             typedef OutEdgeIterDiff InEdgeIterDiff;
2396 
2397             typedef in_edge_iter< InEdgeIter, vertex_descriptor,
2398                 edge_descriptor, InEdgeIterDiff >
2399                 in_edge_iterator;
2400 
2401             typedef typename inv_adjacency_iterator_generator< graph_type,
2402                 vertex_descriptor, in_edge_iterator >::type
2403                 inv_adjacency_iterator;
2404 
2405             // Edge Iterator
2406 
2407             typedef std::iterator_traits< EdgeIter > EdgeIterTraits;
2408             typedef typename EdgeIterTraits::iterator_category EdgeIterCat;
2409             typedef typename EdgeIterTraits::difference_type EdgeIterDiff;
2410 
2411             typedef undirected_edge_iter< EdgeIter, edge_descriptor,
2412                 EdgeIterDiff >
2413                 UndirectedEdgeIter; // also used for bidirectional
2414 
2415             typedef adj_list_edge_iterator< vertex_iterator, out_edge_iterator,
2416                 graph_type >
2417                 DirectedEdgeIter;
2418 
2419             typedef typename mpl::if_< on_edge_storage, DirectedEdgeIter,
2420                 UndirectedEdgeIter >::type edge_iterator;
2421 
2422             // stored_vertex and StoredVertexList
2423             typedef typename container_gen< VertexListS, vertex_ptr >::type
2424                 SeqStoredVertexList;
2425             struct seq_stored_vertex
2426             {
2427                 seq_stored_vertex() {}
2428                 seq_stored_vertex(const VertexProperty& p) : m_property(p) {}
2429                 OutEdgeList m_out_edges;
2430                 VertexProperty m_property;
2431                 typename SeqStoredVertexList::iterator m_position;
2432             };
2433             struct bidir_seq_stored_vertex
2434             {
2435                 bidir_seq_stored_vertex() {}
2436                 bidir_seq_stored_vertex(const VertexProperty& p) : m_property(p)
2437                 {
2438                 }
2439                 OutEdgeList m_out_edges;
2440                 InEdgeList m_in_edges;
2441                 VertexProperty m_property;
2442                 typename SeqStoredVertexList::iterator m_position;
2443             };
2444             struct rand_stored_vertex
2445             {
2446                 rand_stored_vertex() {}
2447                 rand_stored_vertex(const VertexProperty& p) : m_property(p) {}
2448                 OutEdgeList m_out_edges;
2449                 VertexProperty m_property;
2450             };
2451             struct bidir_rand_stored_vertex
2452             {
2453                 bidir_rand_stored_vertex() {}
2454                 bidir_rand_stored_vertex(const VertexProperty& p)
2455                 : m_property(p)
2456                 {
2457                 }
2458                 OutEdgeList m_out_edges;
2459                 InEdgeList m_in_edges;
2460                 VertexProperty m_property;
2461             };
2462             typedef typename mpl::if_< is_rand_access,
2463                 typename mpl::if_< BidirectionalT, bidir_rand_stored_vertex,
2464                     rand_stored_vertex >::type,
2465                 typename mpl::if_< BidirectionalT, bidir_seq_stored_vertex,
2466                     seq_stored_vertex >::type >::type StoredVertex;
2467             struct stored_vertex : public StoredVertex
2468             {
2469                 stored_vertex() {}
2470                 stored_vertex(const VertexProperty& p) : StoredVertex(p) {}
2471             };
2472 
2473             typedef typename container_gen< VertexListS, stored_vertex >::type
2474                 RandStoredVertexList;
2475             typedef typename mpl::if_< is_rand_access, RandStoredVertexList,
2476                 SeqStoredVertexList >::type StoredVertexList;
2477         }; // end of config
2478 
2479         typedef typename mpl::if_< BidirectionalT,
2480             bidirectional_graph_helper_with_property< config >,
2481             typename mpl::if_< DirectedT, directed_graph_helper< config >,
2482                 undirected_graph_helper< config > >::type >::type
2483             DirectedHelper;
2484 
2485         typedef typename mpl::if_< is_rand_access,
2486             vec_adj_list_impl< Graph, config, DirectedHelper >,
2487             adj_list_impl< Graph, config, DirectedHelper > >::type type;
2488     };
2489 
2490 } // namespace detail
2491 
2492 //=========================================================================
2493 // Vertex Property Maps
2494 
2495 template < class Graph, class ValueType, class Reference, class Tag >
2496 struct adj_list_vertex_property_map
2497 : public boost::put_get_helper< Reference,
2498       adj_list_vertex_property_map< Graph, ValueType, Reference, Tag > >
2499 {
2500     typedef typename Graph::stored_vertex StoredVertex;
2501     typedef ValueType value_type;
2502     typedef Reference reference;
2503     typedef typename Graph::vertex_descriptor key_type;
2504     typedef boost::lvalue_property_map_tag category;
2505     inline adj_list_vertex_property_map(const Graph* = 0, Tag tag = Tag())
2506     : m_tag(tag)
2507     {
2508     }
2509     inline Reference operator[](key_type v) const
2510     {
2511         StoredVertex* sv = (StoredVertex*)v;
2512         return get_property_value(sv->m_property, m_tag);
2513     }
2514     inline Reference operator()(key_type v) const
2515     {
2516         return this->operator[](v);
2517     }
2518     Tag m_tag;
2519 };
2520 
2521 template < class Graph, class Property, class PropRef >
2522 struct adj_list_vertex_all_properties_map
2523 : public boost::put_get_helper< PropRef,
2524       adj_list_vertex_all_properties_map< Graph, Property, PropRef > >
2525 {
2526     typedef typename Graph::stored_vertex StoredVertex;
2527     typedef Property value_type;
2528     typedef PropRef reference;
2529     typedef typename Graph::vertex_descriptor key_type;
2530     typedef boost::lvalue_property_map_tag category;
2531     inline adj_list_vertex_all_properties_map(
2532         const Graph* = 0, vertex_all_t = vertex_all_t())
2533     {
2534     }
2535     inline PropRef operator[](key_type v) const
2536     {
2537         StoredVertex* sv = (StoredVertex*)v;
2538         return sv->m_property;
2539     }
2540     inline PropRef operator()(key_type v) const { return this->operator[](v); }
2541 };
2542 
2543 template < class Graph, class GraphPtr, class ValueType, class Reference,
2544     class Tag >
2545 struct vec_adj_list_vertex_property_map
2546 : public boost::put_get_helper< Reference,
2547       vec_adj_list_vertex_property_map< Graph, GraphPtr, ValueType, Reference,
2548           Tag > >
2549 {
2550     typedef ValueType value_type;
2551     typedef Reference reference;
2552     typedef typename boost::graph_traits< Graph >::vertex_descriptor key_type;
2553     typedef boost::lvalue_property_map_tag category;
2554     vec_adj_list_vertex_property_map(GraphPtr g = 0, Tag tag = Tag())
2555     : m_g(g), m_tag(tag)
2556     {
2557     }
2558     inline Reference operator[](key_type v) const
2559     {
2560         return get_property_value(m_g->m_vertices[v].m_property, m_tag);
2561     }
2562     inline Reference operator()(key_type v) const
2563     {
2564         return this->operator[](v);
2565     }
2566     GraphPtr m_g;
2567     Tag m_tag;
2568 };
2569 
2570 template < class Graph, class GraphPtr, class Property, class PropertyRef >
2571 struct vec_adj_list_vertex_all_properties_map
2572 : public boost::put_get_helper< PropertyRef,
2573       vec_adj_list_vertex_all_properties_map< Graph, GraphPtr, Property,
2574           PropertyRef > >
2575 {
2576     typedef Property value_type;
2577     typedef PropertyRef reference;
2578     typedef typename boost::graph_traits< Graph >::vertex_descriptor key_type;
2579     typedef boost::lvalue_property_map_tag category;
2580     vec_adj_list_vertex_all_properties_map(
2581         GraphPtr g = 0, vertex_all_t = vertex_all_t())
2582     : m_g(g)
2583     {
2584     }
2585     inline PropertyRef operator[](key_type v) const
2586     {
2587         return m_g->m_vertices[v].m_property;
2588     }
2589     inline PropertyRef operator()(key_type v) const
2590     {
2591         return this->operator[](v);
2592     }
2593     GraphPtr m_g;
2594 };
2595 
2596 struct adj_list_any_vertex_pa
2597 {
2598     template < class Tag, class Graph, class Property > struct bind_
2599     {
2600         typedef typename property_value< Property, Tag >::type value_type;
2601         typedef value_type& reference;
2602         typedef const value_type& const_reference;
2603 
2604         typedef adj_list_vertex_property_map< Graph, value_type, reference,
2605             Tag >
2606             type;
2607         typedef adj_list_vertex_property_map< Graph, value_type,
2608             const_reference, Tag >
2609             const_type;
2610     };
2611 };
2612 struct adj_list_all_vertex_pa
2613 {
2614     template < class Tag, class Graph, class Property > struct bind_
2615     {
2616         typedef typename Graph::vertex_descriptor Vertex;
2617         typedef adj_list_vertex_all_properties_map< Graph, Property, Property& >
2618             type;
2619         typedef adj_list_vertex_all_properties_map< Graph, Property,
2620             const Property& >
2621             const_type;
2622     };
2623 };
2624 
2625 template < class Property, class Vertex >
2626 struct vec_adj_list_vertex_id_map
2627 : public boost::put_get_helper< Vertex,
2628       vec_adj_list_vertex_id_map< Property, Vertex > >
2629 {
2630     typedef Vertex value_type;
2631     typedef Vertex key_type;
2632     typedef Vertex reference;
2633     typedef boost::readable_property_map_tag category;
2634     inline vec_adj_list_vertex_id_map() {}
2635     template < class Graph >
2636     inline vec_adj_list_vertex_id_map(const Graph&, vertex_index_t)
2637     {
2638     }
2639     inline value_type operator[](key_type v) const { return v; }
2640     inline value_type operator()(key_type v) const { return v; }
2641 };
2642 
2643 struct vec_adj_list_any_vertex_pa
2644 {
2645     template < class Tag, class Graph, class Property > struct bind_
2646     {
2647         typedef typename property_value< Property, Tag >::type value_type;
2648         typedef value_type& reference;
2649         typedef const value_type& const_reference;
2650 
2651         typedef vec_adj_list_vertex_property_map< Graph, Graph*, value_type,
2652             reference, Tag >
2653             type;
2654         typedef vec_adj_list_vertex_property_map< Graph, const Graph*,
2655             value_type, const_reference, Tag >
2656             const_type;
2657     };
2658 };
2659 struct vec_adj_list_id_vertex_pa
2660 {
2661     template < class Tag, class Graph, class Property > struct bind_
2662     {
2663         typedef typename Graph::vertex_descriptor Vertex;
2664         typedef vec_adj_list_vertex_id_map< Property, Vertex > type;
2665         typedef vec_adj_list_vertex_id_map< Property, Vertex > const_type;
2666     };
2667 };
2668 struct vec_adj_list_all_vertex_pa
2669 {
2670     template < class Tag, class Graph, class Property > struct bind_
2671     {
2672         typedef typename Graph::vertex_descriptor Vertex;
2673         typedef vec_adj_list_vertex_all_properties_map< Graph, Graph*, Property,
2674             Property& >
2675             type;
2676         typedef vec_adj_list_vertex_all_properties_map< Graph, const Graph*,
2677             Property, const Property& >
2678             const_type;
2679     };
2680 };
2681 namespace detail
2682 {
2683     template < class Tag, class Graph, class Property >
2684     struct adj_list_choose_vertex_pa
2685     : boost::mpl::if_< boost::is_same< Tag, vertex_all_t >,
2686           adj_list_all_vertex_pa, adj_list_any_vertex_pa >::type ::
2687           template bind_< Tag, Graph, Property >
2688     {
2689     };
2690 
2691     template < class Tag > struct vec_adj_list_choose_vertex_pa_helper
2692     {
2693         typedef vec_adj_list_any_vertex_pa type;
2694     };
2695     template <> struct vec_adj_list_choose_vertex_pa_helper< vertex_index_t >
2696     {
2697         typedef vec_adj_list_id_vertex_pa type;
2698     };
2699     template <> struct vec_adj_list_choose_vertex_pa_helper< vertex_all_t >
2700     {
2701         typedef vec_adj_list_all_vertex_pa type;
2702     };
2703     template < class Tag, class Graph, class Property >
2704     struct vec_adj_list_choose_vertex_pa
2705     : vec_adj_list_choose_vertex_pa_helper< Tag >::type::template bind_< Tag,
2706           Graph, Property >
2707     {
2708     };
2709 } // namespace detail
2710 
2711 //=========================================================================
2712 // Edge Property Map
2713 
2714 template < class Directed, class Value, class Ref, class Vertex, class Property,
2715     class Tag >
2716 struct adj_list_edge_property_map
2717 : public put_get_helper< Ref,
2718       adj_list_edge_property_map< Directed, Value, Ref, Vertex, Property,
2719           Tag > >
2720 {
2721     Tag tag;
2722     explicit adj_list_edge_property_map(Tag tag = Tag()) : tag(tag) {}
2723 
2724     typedef Value value_type;
2725     typedef Ref reference;
2726     typedef detail::edge_desc_impl< Directed, Vertex > key_type;
2727     typedef boost::lvalue_property_map_tag category;
2728     inline Ref operator[](key_type e) const
2729     {
2730         Property& p = *(Property*)e.get_property();
2731         return get_property_value(p, tag);
2732     }
2733     inline Ref operator()(key_type e) const { return this->operator[](e); }
2734 };
2735 
2736 template < class Directed, class Property, class PropRef, class PropPtr,
2737     class Vertex >
2738 struct adj_list_edge_all_properties_map
2739 : public put_get_helper< PropRef,
2740       adj_list_edge_all_properties_map< Directed, Property, PropRef, PropPtr,
2741           Vertex > >
2742 {
2743     explicit adj_list_edge_all_properties_map(edge_all_t = edge_all_t()) {}
2744     typedef Property value_type;
2745     typedef PropRef reference;
2746     typedef detail::edge_desc_impl< Directed, Vertex > key_type;
2747     typedef boost::lvalue_property_map_tag category;
2748     inline PropRef operator[](key_type e) const
2749     {
2750         return *(PropPtr)e.get_property();
2751     }
2752     inline PropRef operator()(key_type e) const { return this->operator[](e); }
2753 };
2754 
2755 // Edge Property Maps
2756 
2757 namespace detail
2758 {
2759     struct adj_list_any_edge_pmap
2760     {
2761         template < class Graph, class Property, class Tag > struct bind_
2762         {
2763             typedef typename property_value< Property, Tag >::type value_type;
2764             typedef value_type& reference;
2765             typedef const value_type& const_reference;
2766 
2767             typedef adj_list_edge_property_map<
2768                 typename Graph::directed_category, value_type, reference,
2769                 typename Graph::vertex_descriptor, Property, Tag >
2770                 type;
2771             typedef adj_list_edge_property_map<
2772                 typename Graph::directed_category, value_type, const_reference,
2773                 typename Graph::vertex_descriptor, const Property, Tag >
2774                 const_type;
2775         };
2776     };
2777     struct adj_list_all_edge_pmap
2778     {
2779         template < class Graph, class Property, class Tag > struct bind_
2780         {
2781             typedef adj_list_edge_all_properties_map<
2782                 typename Graph::directed_category, Property, Property&,
2783                 Property*, typename Graph::vertex_descriptor >
2784                 type;
2785             typedef adj_list_edge_all_properties_map<
2786                 typename Graph::directed_category, Property, const Property&,
2787                 const Property*, typename Graph::vertex_descriptor >
2788                 const_type;
2789         };
2790     };
2791 
2792     template < class Tag > struct adj_list_choose_edge_pmap_helper
2793     {
2794         typedef adj_list_any_edge_pmap type;
2795     };
2796     template <> struct adj_list_choose_edge_pmap_helper< edge_all_t >
2797     {
2798         typedef adj_list_all_edge_pmap type;
2799     };
2800     template < class Tag, class Graph, class Property >
2801     struct adj_list_choose_edge_pmap
2802     : adj_list_choose_edge_pmap_helper< Tag >::type::template bind_< Graph,
2803           Property, Tag >
2804     {
2805     };
2806     struct adj_list_edge_property_selector
2807     {
2808         template < class Graph, class Property, class Tag >
2809         struct bind_ : adj_list_choose_edge_pmap< Tag, Graph, Property >
2810         {
2811         };
2812     };
2813 } // namespace detail
2814 
2815 template <> struct edge_property_selector< adj_list_tag >
2816 {
2817     typedef detail::adj_list_edge_property_selector type;
2818 };
2819 template <> struct edge_property_selector< vec_adj_list_tag >
2820 {
2821     typedef detail::adj_list_edge_property_selector type;
2822 };
2823 
2824 // Vertex Property Maps
2825 
2826 struct adj_list_vertex_property_selector
2827 {
2828     template < class Graph, class Property, class Tag >
2829     struct bind_ : detail::adj_list_choose_vertex_pa< Tag, Graph, Property >
2830     {
2831     };
2832 };
2833 template <> struct vertex_property_selector< adj_list_tag >
2834 {
2835     typedef adj_list_vertex_property_selector type;
2836 };
2837 
2838 struct vec_adj_list_vertex_property_selector
2839 {
2840     template < class Graph, class Property, class Tag >
2841     struct bind_ : detail::vec_adj_list_choose_vertex_pa< Tag, Graph, Property >
2842     {
2843     };
2844 };
2845 template <> struct vertex_property_selector< vec_adj_list_tag >
2846 {
2847     typedef vec_adj_list_vertex_property_selector type;
2848 };
2849 
2850 } // namespace boost
2851 
2852 namespace boost
2853 {
2854 
2855 template < typename V > struct hash< boost::detail::stored_edge< V > >
2856 {
2857     std::size_t operator()(const boost::detail::stored_edge< V >& e) const
2858     {
2859         return hash< V >()(e.m_target);
2860     }
2861 };
2862 
2863 template < typename V, typename P >
2864 struct hash< boost::detail::stored_edge_property< V, P > >
2865 {
2866     std::size_t operator()(
2867         const boost::detail::stored_edge_property< V, P >& e) const
2868     {
2869         return hash< V >()(e.m_target);
2870     }
2871 };
2872 
2873 template < typename V, typename I, typename P >
2874 struct hash< boost::detail::stored_edge_iter< V, I, P > >
2875 {
2876     std::size_t operator()(
2877         const boost::detail::stored_edge_iter< V, I, P >& e) const
2878     {
2879         return hash< V >()(e.m_target);
2880     }
2881 };
2882 
2883 }
2884 
2885 #endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT
2886 
2887 /*
2888   Implementation Notes:
2889 
2890   Many of the public interface functions in this file would have been
2891   more conveniently implemented as inline friend functions.
2892   However there are a few compiler bugs that make that approach
2893   non-portable.
2894 
2895   1. g++ inline friend in namespace bug
2896   2. g++ using clause doesn't work with inline friends
2897   3. VC++ doesn't have Koenig lookup
2898 
2899   For these reasons, the functions were all written as non-inline free
2900   functions, and static cast was used to convert from the helper
2901   class to the adjacency_list derived class.
2902 
2903   Looking back, it might have been better to write out all functions
2904   in terms of the adjacency_list, and then use a tag to dispatch
2905   to the various helpers instead of using inheritance.
2906 
2907  */