| 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
 |