602 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			602 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| //  (C) Copyright Jeremy Siek 2004 
 | |
| //  (C) Copyright Thomas Claveirole 2010
 | |
| //  (C) Copyright Ignacy Gawedzki 2010
 | |
| //  Distributed under the Boost Software License, Version 1.0. (See
 | |
| //  accompanying file LICENSE_1_0.txt or copy at
 | |
| //  http://www.boost.org/LICENSE_1_0.txt)
 | |
| 
 | |
| #ifndef BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
 | |
| #define BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
 | |
| 
 | |
| // Sure would be nice to be able to forward declare these
 | |
| // instead of pulling in all the headers. Too bad that
 | |
| // is not legal. There ought to be a standard <stlfwd> header. -JGS 
 | |
| 
 | |
| #include <boost/next_prior.hpp>
 | |
| 
 | |
| #include <algorithm>   // for std::remove
 | |
| #include <utility>
 | |
| #include <vector>
 | |
| #include <list>
 | |
| #include <map>
 | |
| #include <set>
 | |
| #include <boost/unordered_set.hpp>
 | |
| #include <boost/unordered_map.hpp>
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
 | |
| #include <unordered_set>
 | |
| #endif
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
 | |
| #include <unordered_map>
 | |
| #endif
 | |
| 
 | |
| #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
 | |
| #define BOOST_PENDING_FWD_TYPE(type) const type&
 | |
| #define BOOST_PENDING_FWD_VALUE(type, var) (var)
 | |
| #else
 | |
| #define BOOST_PENDING_FWD_TYPE(type) type&&
 | |
| #define BOOST_PENDING_FWD_VALUE(type, var) (std::forward<type>((var)))
 | |
| #endif
 | |
| 
 | |
| // The content of this file is in 'graph_detail' because otherwise
 | |
| // there will be name clashes with 
 | |
| // sandbox/boost/sequence_algo/container_traits.hpp
 | |
| // The 'detail' subnamespace will still cause problems.
 | |
| namespace boost { namespace graph_detail {
 | |
| 
 | |
|   //======================================================================
 | |
|   // Container Category Tags
 | |
|   //
 | |
|   //   They use virtual inheritance because there are lots of
 | |
|   //   inheritance diamonds.
 | |
| 
 | |
|   struct container_tag { };
 | |
|   struct forward_container_tag : virtual public container_tag { };
 | |
|   struct reversible_container_tag : virtual public forward_container_tag { };
 | |
|   struct random_access_container_tag
 | |
|     : virtual public reversible_container_tag { };
 | |
|   
 | |
|   struct sequence_tag : virtual public forward_container_tag { };
 | |
| 
 | |
|   struct associative_container_tag : virtual public forward_container_tag { };
 | |
| 
 | |
|   struct sorted_associative_container_tag 
 | |
|     : virtual public associative_container_tag,
 | |
|       virtual public reversible_container_tag { };
 | |
| 
 | |
|   struct front_insertion_sequence_tag : virtual public sequence_tag { };
 | |
|   struct back_insertion_sequence_tag : virtual public sequence_tag { };
 | |
| 
 | |
|   struct unique_associative_container_tag 
 | |
|     : virtual public associative_container_tag { };
 | |
|   struct multiple_associative_container_tag 
 | |
|     : virtual public associative_container_tag { };
 | |
|   struct simple_associative_container_tag 
 | |
|     : virtual public associative_container_tag { };
 | |
|   struct pair_associative_container_tag 
 | |
|     : virtual public associative_container_tag { };
 | |
| 
 | |
| 
 | |
|   //======================================================================
 | |
|   // Iterator Stability Tags
 | |
|   //
 | |
|   // Do mutating operations such as insert/erase/resize invalidate all
 | |
|   // outstanding iterators?
 | |
| 
 | |
|   struct stable_tag { };
 | |
|   struct unstable_tag { };
 | |
| 
 | |
|   //======================================================================
 | |
|   // Container Traits Class and container_category() function
 | |
| 
 | |
|   // don't use this unless there is partial specialization 
 | |
|   template <class Container>
 | |
|   struct container_traits {
 | |
|     typedef typename Container::category category;
 | |
|     typedef typename Container::iterator_stability iterator_stability;
 | |
|   };
 | |
| 
 | |
|   // Use this as a compile-time assertion that X is stable
 | |
|   inline void require_stable(stable_tag) { }
 | |
| 
 | |
|   // std::vector
 | |
|   struct vector_tag :
 | |
|     virtual public random_access_container_tag,
 | |
|     virtual public back_insertion_sequence_tag { };
 | |
| 
 | |
|   template <class T, class Alloc>
 | |
|   vector_tag container_category(const std::vector<T,Alloc>&)
 | |
|     { return vector_tag(); }
 | |
| 
 | |
|   template <class T, class Alloc>
 | |
|   unstable_tag iterator_stability(const std::vector<T,Alloc>&)
 | |
|     { return unstable_tag(); }
 | |
| 
 | |
|   template <class T, class Alloc>
 | |
|   struct container_traits< std::vector<T,Alloc> > {
 | |
|     typedef vector_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
| 
 | |
|   // std::list
 | |
|   struct list_tag :
 | |
|     virtual public reversible_container_tag,
 | |
|     virtual public back_insertion_sequence_tag
 | |
|     // this causes problems for push_dispatch...
 | |
|     //    virtual public front_insertion_sequence_tag
 | |
|     { };
 | |
| 
 | |
|   template <class T, class Alloc>
 | |
|   list_tag container_category(const std::list<T,Alloc>&)
 | |
|     { return list_tag(); }
 | |
| 
 | |
|   template <class T, class Alloc>
 | |
|   stable_tag iterator_stability(const std::list<T,Alloc>&)
 | |
|     { return stable_tag(); }
 | |
| 
 | |
|   template <class T, class Alloc>
 | |
|   struct container_traits< std::list<T,Alloc> > {
 | |
|     typedef list_tag category;
 | |
|     typedef stable_tag iterator_stability;
 | |
|   };
 | |
| 
 | |
|   // std::set
 | |
|   struct set_tag :
 | |
|     virtual public sorted_associative_container_tag,
 | |
|     virtual public simple_associative_container_tag,
 | |
|     virtual public unique_associative_container_tag 
 | |
|     { };
 | |
| 
 | |
|   template <class Key, class Cmp, class Alloc> 
 | |
|   set_tag container_category(const std::set<Key,Cmp,Alloc>&)
 | |
|   { return set_tag(); }
 | |
| 
 | |
|   template <class Key, class Cmp, class Alloc> 
 | |
|   stable_tag iterator_stability(const std::set<Key,Cmp,Alloc>&)
 | |
|   { return stable_tag(); }
 | |
| 
 | |
|   template <class Key, class Cmp, class Alloc> 
 | |
|   struct container_traits< std::set<Key,Cmp,Alloc> > {
 | |
|     typedef set_tag category;
 | |
|     typedef stable_tag iterator_stability;
 | |
|   };
 | |
| 
 | |
|   // std::multiset
 | |
|   struct multiset_tag :
 | |
|     virtual public sorted_associative_container_tag,
 | |
|     virtual public simple_associative_container_tag,
 | |
|     virtual public multiple_associative_container_tag 
 | |
|     { };
 | |
| 
 | |
|   template <class Key, class Cmp, class Alloc> 
 | |
|   multiset_tag container_category(const std::multiset<Key,Cmp,Alloc>&)
 | |
|   { return multiset_tag(); }
 | |
| 
 | |
|   template <class Key, class Cmp, class Alloc> 
 | |
|   stable_tag iterator_stability(const std::multiset<Key,Cmp,Alloc>&)
 | |
|   { return stable_tag(); }
 | |
| 
 | |
|   template <class Key, class Cmp, class Alloc> 
 | |
|   struct container_traits< std::multiset<Key,Cmp,Alloc> > {
 | |
|     typedef multiset_tag category;
 | |
|     typedef stable_tag iterator_stability;
 | |
|   };
 | |
| 
 | |
|   // deque
 | |
| 
 | |
|   // std::map
 | |
|   struct map_tag :
 | |
|     virtual public sorted_associative_container_tag,
 | |
|     virtual public pair_associative_container_tag,
 | |
|     virtual public unique_associative_container_tag 
 | |
|     { };
 | |
| 
 | |
|   template <class Key, class T, class Cmp, class Alloc> 
 | |
|   struct container_traits< std::map<Key,T,Cmp,Alloc> > {
 | |
|     typedef map_tag category;
 | |
|     typedef stable_tag iterator_stability;
 | |
|   };
 | |
| 
 | |
|   template <class Key, class T, class Cmp, class Alloc> 
 | |
|   map_tag container_category(const std::map<Key,T,Cmp,Alloc>&)
 | |
|   { return map_tag(); }
 | |
| 
 | |
|   template <class Key, class T, class Cmp, class Alloc> 
 | |
|   stable_tag iterator_stability(const std::map<Key,T,Cmp,Alloc>&)
 | |
|   { return stable_tag(); }
 | |
| 
 | |
|   // std::multimap
 | |
|   struct multimap_tag :
 | |
|     virtual public sorted_associative_container_tag,
 | |
|     virtual public pair_associative_container_tag,
 | |
|     virtual public multiple_associative_container_tag 
 | |
|     { };
 | |
| 
 | |
|   template <class Key, class T, class Cmp, class Alloc> 
 | |
|   struct container_traits< std::multimap<Key,T,Cmp,Alloc> > {
 | |
|     typedef multimap_tag category;
 | |
|     typedef stable_tag iterator_stability;
 | |
|   };
 | |
| 
 | |
|   template <class Key, class T, class Cmp, class Alloc> 
 | |
|   multimap_tag container_category(const std::multimap<Key,T,Cmp,Alloc>&)
 | |
|   { return multimap_tag(); }
 | |
| 
 | |
|   template <class Key, class T, class Cmp, class Alloc> 
 | |
|   stable_tag iterator_stability(const std::multimap<Key,T,Cmp,Alloc>&)
 | |
|   { return stable_tag(); }
 | |
| 
 | |
| 
 | |
|  // hash_set, hash_map
 | |
| 
 | |
|   struct unordered_set_tag :
 | |
|     virtual public simple_associative_container_tag,
 | |
|     virtual public unique_associative_container_tag
 | |
|     { };
 | |
| 
 | |
|   struct unordered_multiset_tag :
 | |
|     virtual public simple_associative_container_tag,
 | |
|     virtual public multiple_associative_container_tag
 | |
|     { };
 | |
| 
 | |
| 
 | |
|   struct unordered_map_tag :
 | |
|     virtual public pair_associative_container_tag,
 | |
|     virtual public unique_associative_container_tag
 | |
|     { };
 | |
| 
 | |
|   struct unordered_multimap_tag :
 | |
|     virtual public pair_associative_container_tag,
 | |
|     virtual public multiple_associative_container_tag
 | |
|     { };
 | |
| 
 | |
| 
 | |
|   template <class Key, class Eq, class Hash, class Alloc> 
 | |
|   struct container_traits< boost::unordered_set<Key,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_set_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   struct container_traits< boost::unordered_map<Key,T,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_map_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   struct container_traits< boost::unordered_multiset<Key,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_multiset_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   struct container_traits< boost::unordered_multimap<Key,T,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_multimap_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
| 
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unordered_set_tag
 | |
|   container_category(const boost::unordered_set<Key,Eq,Hash,Alloc>&)
 | |
|   { return unordered_set_tag(); }
 | |
| 
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unordered_map_tag
 | |
|   container_category(const boost::unordered_map<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unordered_map_tag(); }
 | |
| 
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag iterator_stability(const boost::unordered_set<Key,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
| 
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag iterator_stability(const boost::unordered_map<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unordered_multiset_tag
 | |
|   container_category(const boost::unordered_multiset<Key,Eq,Hash,Alloc>&)
 | |
|   { return unordered_multiset_tag(); }
 | |
| 
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unordered_multimap_tag
 | |
|   container_category(const boost::unordered_multimap<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unordered_multimap_tag(); }
 | |
| 
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag
 | |
|   iterator_stability(const boost::unordered_multiset<Key,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
| 
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag
 | |
|   iterator_stability(const boost::unordered_multimap<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
 | |
|   template <class Key, class Eq, class Hash, class Alloc> 
 | |
|   struct container_traits< std::unordered_set<Key,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_set_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
| #endif
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   struct container_traits< std::unordered_map<Key,T,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_map_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
| #endif
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   struct container_traits< std::unordered_multiset<Key,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_multiset_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
| #endif
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   struct container_traits< std::unordered_multimap<Key,T,Eq,Hash,Alloc> > {
 | |
|     typedef unordered_multimap_tag category;
 | |
|     typedef unstable_tag iterator_stability;
 | |
|   };
 | |
| #endif
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unordered_set_tag
 | |
|   container_category(const std::unordered_set<Key,Eq,Hash,Alloc>&)
 | |
|   { return unordered_set_tag(); }
 | |
| #endif
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unordered_map_tag
 | |
|   container_category(const std::unordered_map<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unordered_map_tag(); }
 | |
| #endif
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag iterator_stability(const std::unordered_set<Key,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
| #endif
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag iterator_stability(const std::unordered_map<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
| #endif
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unordered_multiset_tag
 | |
|   container_category(const std::unordered_multiset<Key,Eq,Hash,Alloc>&)
 | |
|   { return unordered_multiset_tag(); }
 | |
| #endif
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unordered_multimap_tag
 | |
|   container_category(const std::unordered_multimap<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unordered_multimap_tag(); }
 | |
| #endif
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
 | |
|   template <class Key, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag
 | |
|   iterator_stability(const std::unordered_multiset<Key,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
| #endif
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
 | |
|   template <class Key, class T, class Eq, class Hash, class Alloc>
 | |
|   unstable_tag
 | |
|   iterator_stability(const std::unordered_multimap<Key,T,Eq,Hash,Alloc>&)
 | |
|   { return unstable_tag(); }
 | |
| #endif
 | |
| 
 | |
| 
 | |
|   //===========================================================================
 | |
|   // Generalized Container Functions
 | |
| 
 | |
| 
 | |
|   // Erase
 | |
|   template <class Sequence, class T>
 | |
|   void erase_dispatch(Sequence& c, const T& x, 
 | |
|                       sequence_tag)
 | |
|   {
 | |
|     c.erase(std::remove(c.begin(), c.end(), x), c.end());
 | |
|   }
 | |
| 
 | |
|   template <class AssociativeContainer, class T>
 | |
|   void erase_dispatch(AssociativeContainer& c, const T& x, 
 | |
|                       associative_container_tag)
 | |
|   {
 | |
|     c.erase(x);
 | |
|   }
 | |
|   template <class Container, class T>
 | |
|   void erase(Container& c, const T& x)
 | |
|   {
 | |
|     erase_dispatch(c, x, container_category(c));
 | |
|   }
 | |
| 
 | |
|   // Erase If
 | |
|   template <class Sequence, class Predicate, class IteratorStability>
 | |
|   void erase_if_dispatch(Sequence& c, Predicate p,
 | |
|                          sequence_tag, IteratorStability)
 | |
|   {
 | |
| #if 0
 | |
|     c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
 | |
| #else
 | |
|     if (! c.empty())
 | |
|       c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
 | |
| #endif
 | |
|   }
 | |
|   template <class AssociativeContainer, class Predicate>
 | |
|   void erase_if_dispatch(AssociativeContainer& c, Predicate p,
 | |
|                          associative_container_tag, stable_tag)
 | |
|   {
 | |
|     typename AssociativeContainer::iterator i, next;
 | |
|     for (i = next = c.begin(); next != c.end(); i = next) {
 | |
|       ++next;
 | |
|       if (p(*i))
 | |
|         c.erase(i);
 | |
|     }
 | |
|   }
 | |
|   template <class AssociativeContainer, class Predicate>
 | |
|   void erase_if_dispatch(AssociativeContainer& c, Predicate p,
 | |
|                          associative_container_tag, unstable_tag)
 | |
|   {
 | |
|     // This method is really slow, so hopefully we won't have any
 | |
|     // associative containers with unstable iterators!
 | |
|     // Is there a better way to do this?
 | |
|     typename AssociativeContainer::iterator i;
 | |
|     typename AssociativeContainer::size_type n = c.size();
 | |
|     while (n--)
 | |
|       for (i = c.begin(); i != c.end(); ++i)
 | |
|         if (p(*i)) {
 | |
|           c.erase(i);
 | |
|           break;
 | |
|         }
 | |
|   }
 | |
|   template <class Container, class Predicate>
 | |
|   void erase_if(Container& c, Predicate p)
 | |
|   {
 | |
|     erase_if_dispatch(c, p, container_category(c), iterator_stability(c));
 | |
|   }
 | |
| 
 | |
|   // Push
 | |
|   template <class Container, class T>
 | |
|   std::pair<typename Container::iterator, bool>
 | |
|   push_dispatch(Container& c, BOOST_PENDING_FWD_TYPE(T) v, back_insertion_sequence_tag)
 | |
|   {
 | |
|     c.push_back(BOOST_PENDING_FWD_VALUE(T, v));
 | |
|     return std::make_pair(boost::prior(c.end()), true);
 | |
|   }
 | |
| 
 | |
|   template <class Container, class T>
 | |
|   std::pair<typename Container::iterator, bool>
 | |
|   push_dispatch(Container& c, BOOST_PENDING_FWD_TYPE(T) v, front_insertion_sequence_tag)
 | |
|   {
 | |
|     c.push_front(BOOST_PENDING_FWD_VALUE(T, v));
 | |
|     return std::make_pair(c.begin(), true);
 | |
|   }
 | |
| 
 | |
|   template <class AssociativeContainer, class T>
 | |
|   std::pair<typename AssociativeContainer::iterator, bool>
 | |
|   push_dispatch(AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v, 
 | |
|                 unique_associative_container_tag)
 | |
|   {
 | |
|     return c.insert(BOOST_PENDING_FWD_VALUE(T, v));
 | |
|   }
 | |
| 
 | |
|   template <class AssociativeContainer, class T>
 | |
|   std::pair<typename AssociativeContainer::iterator, bool>
 | |
|   push_dispatch(AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v,
 | |
|                 multiple_associative_container_tag)
 | |
|   {
 | |
|     return std::make_pair(c.insert(BOOST_PENDING_FWD_VALUE(T, v)), true);
 | |
|   }
 | |
| 
 | |
|   template <class Container, class T>
 | |
|   std::pair<typename Container::iterator,bool>
 | |
|   push(Container& c, BOOST_PENDING_FWD_TYPE(T) v)
 | |
|   {
 | |
|     return push_dispatch(c, BOOST_PENDING_FWD_VALUE(T, v), container_category(c));
 | |
|   }
 | |
| 
 | |
|   // Find
 | |
|   template <class Container, class Value>
 | |
|   typename Container::iterator
 | |
|   find_dispatch(Container& c,
 | |
|                 const Value& value,
 | |
|                 container_tag)
 | |
|   {
 | |
|     return std::find(c.begin(), c.end(), value);
 | |
|   }
 | |
| 
 | |
|   template <class AssociativeContainer, class Value>
 | |
|   typename AssociativeContainer::iterator
 | |
|   find_dispatch(AssociativeContainer& c,
 | |
|                 const Value& value,
 | |
|                 associative_container_tag)
 | |
|   {
 | |
|     return c.find(value);
 | |
|   }
 | |
| 
 | |
|   template <class Container, class Value>
 | |
|   typename Container::iterator
 | |
|   find(Container& c,
 | |
|        const Value& value)
 | |
|   {
 | |
|     return find_dispatch(c, value,
 | |
|                          graph_detail::container_category(c));
 | |
|   }
 | |
| 
 | |
|   // Find (const versions)
 | |
|   template <class Container, class Value>
 | |
|   typename Container::const_iterator
 | |
|   find_dispatch(const Container& c,
 | |
|                 const Value& value,
 | |
|                 container_tag)
 | |
|   {
 | |
|     return std::find(c.begin(), c.end(), value);
 | |
|   }
 | |
| 
 | |
|   template <class AssociativeContainer, class Value>
 | |
|   typename AssociativeContainer::const_iterator
 | |
|   find_dispatch(const AssociativeContainer& c,
 | |
|                 const Value& value,
 | |
|                 associative_container_tag)
 | |
|   {
 | |
|     return c.find(value);
 | |
|   }
 | |
| 
 | |
|   template <class Container, class Value>
 | |
|   typename Container::const_iterator
 | |
|   find(const Container& c,
 | |
|        const Value& value)
 | |
|   {
 | |
|     return find_dispatch(c, value,
 | |
|                          graph_detail::container_category(c));
 | |
|   }
 | |
| 
 | |
|   // Equal range
 | |
| #if 0
 | |
|   // Make the dispatch fail if c is not an Associative Container (and thus
 | |
|   // doesn't have equal_range unless it is sorted, which we cannot check
 | |
|   // statically and is not typically true for BGL's uses of this function).
 | |
|   template <class Container,
 | |
|             class LessThanComparable>
 | |
|   std::pair<typename Container::iterator, typename Container::iterator>
 | |
|   equal_range_dispatch(Container& c,
 | |
|                        const LessThanComparable& value,
 | |
|                        container_tag)
 | |
|   {
 | |
|     // c must be sorted for std::equal_range to behave properly.
 | |
|     return std::equal_range(c.begin(), c.end(), value);
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   template <class AssociativeContainer, class Value>
 | |
|   std::pair<typename AssociativeContainer::iterator,
 | |
|             typename AssociativeContainer::iterator>
 | |
|   equal_range_dispatch(AssociativeContainer& c,
 | |
|                        const Value& value,
 | |
|                        associative_container_tag)
 | |
|   {
 | |
|     return c.equal_range(value);
 | |
|   }
 | |
| 
 | |
|   template <class Container, class Value>
 | |
|   std::pair<typename Container::iterator, typename Container::iterator>
 | |
|   equal_range(Container& c,
 | |
|               const Value& value)
 | |
|   {
 | |
|     return equal_range_dispatch(c, value,
 | |
|                                 graph_detail::container_category(c));
 | |
|   }
 | |
| 
 | |
| }} // namespace boost::graph_detail
 | |
| 
 | |
| #undef BOOST_PENDING_FWD_TYPE
 | |
| #undef BOOST_PENDING_FWD_VALUE
 | |
| 
 | |
| #endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
 | 
