123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- // (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
|