Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:31

0001 //  (C) Copyright Jeremy Siek 2004
0002 //  (C) Copyright Thomas Claveirole 2010
0003 //  (C) Copyright Ignacy Gawedzki 2010
0004 //  Distributed under the Boost Software License, Version 1.0. (See
0005 //  accompanying file LICENSE_1_0.txt or copy at
0006 //  http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
0009 #define BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
0010 
0011 // Sure would be nice to be able to forward declare these
0012 // instead of pulling in all the headers. Too bad that
0013 // is not legal. There ought to be a standard <stlfwd> header. -JGS
0014 
0015 #include <boost/next_prior.hpp>
0016 
0017 #include <algorithm> // for std::remove
0018 #include <utility>
0019 #include <vector>
0020 #include <list>
0021 #include <map>
0022 #include <set>
0023 #include <boost/unordered_set.hpp>
0024 #include <boost/unordered_map.hpp>
0025 
0026 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
0027 #include <unordered_set>
0028 #endif
0029 
0030 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
0031 #include <unordered_map>
0032 #endif
0033 
0034 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
0035 #define BOOST_PENDING_FWD_TYPE(type) const type&
0036 #define BOOST_PENDING_FWD_VALUE(type, var) (var)
0037 #else
0038 #define BOOST_PENDING_FWD_TYPE(type) type&&
0039 #define BOOST_PENDING_FWD_VALUE(type, var) (std::forward< type >((var)))
0040 #endif
0041 
0042 // The content of this file is in 'graph_detail' because otherwise
0043 // there will be name clashes with
0044 // sandbox/boost/sequence_algo/container_traits.hpp
0045 // The 'detail' subnamespace will still cause problems.
0046 namespace boost
0047 {
0048 namespace graph_detail
0049 {
0050 
0051     //======================================================================
0052     // Container Category Tags
0053     //
0054     //   They use virtual inheritance because there are lots of
0055     //   inheritance diamonds.
0056 
0057     struct container_tag
0058     {
0059     };
0060     struct forward_container_tag : virtual public container_tag
0061     {
0062     };
0063     struct reversible_container_tag : virtual public forward_container_tag
0064     {
0065     };
0066     struct random_access_container_tag : virtual public reversible_container_tag
0067     {
0068     };
0069 
0070     struct sequence_tag : virtual public forward_container_tag
0071     {
0072     };
0073 
0074     struct associative_container_tag : virtual public forward_container_tag
0075     {
0076     };
0077 
0078     struct sorted_associative_container_tag
0079     : virtual public associative_container_tag,
0080       virtual public reversible_container_tag
0081     {
0082     };
0083 
0084     struct front_insertion_sequence_tag : virtual public sequence_tag
0085     {
0086     };
0087     struct back_insertion_sequence_tag : virtual public sequence_tag
0088     {
0089     };
0090 
0091     struct unique_associative_container_tag
0092     : virtual public associative_container_tag
0093     {
0094     };
0095     struct multiple_associative_container_tag
0096     : virtual public associative_container_tag
0097     {
0098     };
0099     struct simple_associative_container_tag
0100     : virtual public associative_container_tag
0101     {
0102     };
0103     struct pair_associative_container_tag
0104     : virtual public associative_container_tag
0105     {
0106     };
0107 
0108     //======================================================================
0109     // Iterator Stability Tags
0110     //
0111     // Do mutating operations such as insert/erase/resize invalidate all
0112     // outstanding iterators?
0113 
0114     struct stable_tag
0115     {
0116     };
0117     struct unstable_tag
0118     {
0119     };
0120 
0121     //======================================================================
0122     // Container Traits Class and container_category() function
0123 
0124     // don't use this unless there is partial specialization
0125     template < class Container > struct container_traits
0126     {
0127         typedef typename Container::category category;
0128         typedef typename Container::iterator_stability iterator_stability;
0129     };
0130 
0131     // Use this as a compile-time assertion that X is stable
0132     inline void require_stable(stable_tag) {}
0133 
0134     // std::vector
0135     struct vector_tag : virtual public random_access_container_tag,
0136                         virtual public back_insertion_sequence_tag
0137     {
0138     };
0139 
0140     template < class T, class Alloc >
0141     vector_tag container_category(const std::vector< T, Alloc >&)
0142     {
0143         return vector_tag();
0144     }
0145 
0146     template < class T, class Alloc >
0147     unstable_tag iterator_stability(const std::vector< T, Alloc >&)
0148     {
0149         return unstable_tag();
0150     }
0151 
0152     template < class T, class Alloc >
0153     struct container_traits< std::vector< T, Alloc > >
0154     {
0155         typedef vector_tag category;
0156         typedef unstable_tag iterator_stability;
0157     };
0158 
0159     // std::list
0160     struct list_tag : virtual public reversible_container_tag,
0161                       virtual public back_insertion_sequence_tag
0162     // this causes problems for push_dispatch...
0163     //    virtual public front_insertion_sequence_tag
0164     {
0165     };
0166 
0167     template < class T, class Alloc >
0168     list_tag container_category(const std::list< T, Alloc >&)
0169     {
0170         return list_tag();
0171     }
0172 
0173     template < class T, class Alloc >
0174     stable_tag iterator_stability(const std::list< T, Alloc >&)
0175     {
0176         return stable_tag();
0177     }
0178 
0179     template < class T, class Alloc >
0180     struct container_traits< std::list< T, Alloc > >
0181     {
0182         typedef list_tag category;
0183         typedef stable_tag iterator_stability;
0184     };
0185 
0186     // std::set
0187     struct set_tag : virtual public sorted_associative_container_tag,
0188                      virtual public simple_associative_container_tag,
0189                      virtual public unique_associative_container_tag
0190     {
0191     };
0192 
0193     template < class Key, class Cmp, class Alloc >
0194     set_tag container_category(const std::set< Key, Cmp, Alloc >&)
0195     {
0196         return set_tag();
0197     }
0198 
0199     template < class Key, class Cmp, class Alloc >
0200     stable_tag iterator_stability(const std::set< Key, Cmp, Alloc >&)
0201     {
0202         return stable_tag();
0203     }
0204 
0205     template < class Key, class Cmp, class Alloc >
0206     struct container_traits< std::set< Key, Cmp, Alloc > >
0207     {
0208         typedef set_tag category;
0209         typedef stable_tag iterator_stability;
0210     };
0211 
0212     // std::multiset
0213     struct multiset_tag : virtual public sorted_associative_container_tag,
0214                           virtual public simple_associative_container_tag,
0215                           virtual public multiple_associative_container_tag
0216     {
0217     };
0218 
0219     template < class Key, class Cmp, class Alloc >
0220     multiset_tag container_category(const std::multiset< Key, Cmp, Alloc >&)
0221     {
0222         return multiset_tag();
0223     }
0224 
0225     template < class Key, class Cmp, class Alloc >
0226     stable_tag iterator_stability(const std::multiset< Key, Cmp, Alloc >&)
0227     {
0228         return stable_tag();
0229     }
0230 
0231     template < class Key, class Cmp, class Alloc >
0232     struct container_traits< std::multiset< Key, Cmp, Alloc > >
0233     {
0234         typedef multiset_tag category;
0235         typedef stable_tag iterator_stability;
0236     };
0237 
0238     // deque
0239 
0240     // std::map
0241     struct map_tag : virtual public sorted_associative_container_tag,
0242                      virtual public pair_associative_container_tag,
0243                      virtual public unique_associative_container_tag
0244     {
0245     };
0246 
0247     template < class Key, class T, class Cmp, class Alloc >
0248     struct container_traits< std::map< Key, T, Cmp, Alloc > >
0249     {
0250         typedef map_tag category;
0251         typedef stable_tag iterator_stability;
0252     };
0253 
0254     template < class Key, class T, class Cmp, class Alloc >
0255     map_tag container_category(const std::map< Key, T, Cmp, Alloc >&)
0256     {
0257         return map_tag();
0258     }
0259 
0260     template < class Key, class T, class Cmp, class Alloc >
0261     stable_tag iterator_stability(const std::map< Key, T, Cmp, Alloc >&)
0262     {
0263         return stable_tag();
0264     }
0265 
0266     // std::multimap
0267     struct multimap_tag : virtual public sorted_associative_container_tag,
0268                           virtual public pair_associative_container_tag,
0269                           virtual public multiple_associative_container_tag
0270     {
0271     };
0272 
0273     template < class Key, class T, class Cmp, class Alloc >
0274     struct container_traits< std::multimap< Key, T, Cmp, Alloc > >
0275     {
0276         typedef multimap_tag category;
0277         typedef stable_tag iterator_stability;
0278     };
0279 
0280     template < class Key, class T, class Cmp, class Alloc >
0281     multimap_tag container_category(const std::multimap< Key, T, Cmp, Alloc >&)
0282     {
0283         return multimap_tag();
0284     }
0285 
0286     template < class Key, class T, class Cmp, class Alloc >
0287     stable_tag iterator_stability(const std::multimap< Key, T, Cmp, Alloc >&)
0288     {
0289         return stable_tag();
0290     }
0291 
0292     // hash_set, hash_map
0293 
0294     struct unordered_set_tag : virtual public simple_associative_container_tag,
0295                                virtual public unique_associative_container_tag
0296     {
0297     };
0298 
0299     struct unordered_multiset_tag
0300     : virtual public simple_associative_container_tag,
0301       virtual public multiple_associative_container_tag
0302     {
0303     };
0304 
0305     struct unordered_map_tag : virtual public pair_associative_container_tag,
0306                                virtual public unique_associative_container_tag
0307     {
0308     };
0309 
0310     struct unordered_multimap_tag
0311     : virtual public pair_associative_container_tag,
0312       virtual public multiple_associative_container_tag
0313     {
0314     };
0315 
0316     template < class Key, class Eq, class Hash, class Alloc >
0317     struct container_traits< boost::unordered_set< Key, Eq, Hash, Alloc > >
0318     {
0319         typedef unordered_set_tag category;
0320         typedef unstable_tag iterator_stability;
0321     };
0322     template < class Key, class T, class Eq, class Hash, class Alloc >
0323     struct container_traits< boost::unordered_map< Key, T, Eq, Hash, Alloc > >
0324     {
0325         typedef unordered_map_tag category;
0326         typedef unstable_tag iterator_stability;
0327     };
0328     template < class Key, class Eq, class Hash, class Alloc >
0329     struct container_traits< boost::unordered_multiset< Key, Eq, Hash, Alloc > >
0330     {
0331         typedef unordered_multiset_tag category;
0332         typedef unstable_tag iterator_stability;
0333     };
0334     template < class Key, class T, class Eq, class Hash, class Alloc >
0335     struct container_traits<
0336         boost::unordered_multimap< Key, T, Eq, Hash, Alloc > >
0337     {
0338         typedef unordered_multimap_tag category;
0339         typedef unstable_tag iterator_stability;
0340     };
0341 
0342     template < class Key, class Eq, class Hash, class Alloc >
0343     unordered_set_tag container_category(
0344         const boost::unordered_set< Key, Eq, Hash, Alloc >&)
0345     {
0346         return unordered_set_tag();
0347     }
0348 
0349     template < class Key, class T, class Eq, class Hash, class Alloc >
0350     unordered_map_tag container_category(
0351         const boost::unordered_map< Key, T, Eq, Hash, Alloc >&)
0352     {
0353         return unordered_map_tag();
0354     }
0355 
0356     template < class Key, class Eq, class Hash, class Alloc >
0357     unstable_tag iterator_stability(
0358         const boost::unordered_set< Key, Eq, Hash, Alloc >&)
0359     {
0360         return unstable_tag();
0361     }
0362 
0363     template < class Key, class T, class Eq, class Hash, class Alloc >
0364     unstable_tag iterator_stability(
0365         const boost::unordered_map< Key, T, Eq, Hash, Alloc >&)
0366     {
0367         return unstable_tag();
0368     }
0369     template < class Key, class Eq, class Hash, class Alloc >
0370     unordered_multiset_tag container_category(
0371         const boost::unordered_multiset< Key, Eq, Hash, Alloc >&)
0372     {
0373         return unordered_multiset_tag();
0374     }
0375 
0376     template < class Key, class T, class Eq, class Hash, class Alloc >
0377     unordered_multimap_tag container_category(
0378         const boost::unordered_multimap< Key, T, Eq, Hash, Alloc >&)
0379     {
0380         return unordered_multimap_tag();
0381     }
0382 
0383     template < class Key, class Eq, class Hash, class Alloc >
0384     unstable_tag iterator_stability(
0385         const boost::unordered_multiset< Key, Eq, Hash, Alloc >&)
0386     {
0387         return unstable_tag();
0388     }
0389 
0390     template < class Key, class T, class Eq, class Hash, class Alloc >
0391     unstable_tag iterator_stability(
0392         const boost::unordered_multimap< Key, T, Eq, Hash, Alloc >&)
0393     {
0394         return unstable_tag();
0395     }
0396 
0397 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
0398     template < class Key, class Eq, class Hash, class Alloc >
0399     struct container_traits< std::unordered_set< Key, Eq, Hash, Alloc > >
0400     {
0401         typedef unordered_set_tag category;
0402         typedef unstable_tag iterator_stability;
0403     };
0404 #endif
0405 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
0406     template < class Key, class T, class Eq, class Hash, class Alloc >
0407     struct container_traits< std::unordered_map< Key, T, Eq, Hash, Alloc > >
0408     {
0409         typedef unordered_map_tag category;
0410         typedef unstable_tag iterator_stability;
0411     };
0412 #endif
0413 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
0414     template < class Key, class Eq, class Hash, class Alloc >
0415     struct container_traits< std::unordered_multiset< Key, Eq, Hash, Alloc > >
0416     {
0417         typedef unordered_multiset_tag category;
0418         typedef unstable_tag iterator_stability;
0419     };
0420 #endif
0421 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
0422     template < class Key, class T, class Eq, class Hash, class Alloc >
0423     struct container_traits<
0424         std::unordered_multimap< Key, T, Eq, Hash, Alloc > >
0425     {
0426         typedef unordered_multimap_tag category;
0427         typedef unstable_tag iterator_stability;
0428     };
0429 #endif
0430 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
0431     template < class Key, class Eq, class Hash, class Alloc >
0432     unordered_set_tag container_category(
0433         const std::unordered_set< Key, Eq, Hash, Alloc >&)
0434     {
0435         return unordered_set_tag();
0436     }
0437 #endif
0438 
0439 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
0440     template < class Key, class T, class Eq, class Hash, class Alloc >
0441     unordered_map_tag container_category(
0442         const std::unordered_map< Key, T, Eq, Hash, Alloc >&)
0443     {
0444         return unordered_map_tag();
0445     }
0446 #endif
0447 
0448 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
0449     template < class Key, class Eq, class Hash, class Alloc >
0450     unstable_tag iterator_stability(
0451         const std::unordered_set< Key, Eq, Hash, Alloc >&)
0452     {
0453         return unstable_tag();
0454     }
0455 #endif
0456 
0457 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
0458     template < class Key, class T, class Eq, class Hash, class Alloc >
0459     unstable_tag iterator_stability(
0460         const std::unordered_map< Key, T, Eq, Hash, Alloc >&)
0461     {
0462         return unstable_tag();
0463     }
0464 #endif
0465 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
0466     template < class Key, class Eq, class Hash, class Alloc >
0467     unordered_multiset_tag container_category(
0468         const std::unordered_multiset< Key, Eq, Hash, Alloc >&)
0469     {
0470         return unordered_multiset_tag();
0471     }
0472 #endif
0473 
0474 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
0475     template < class Key, class T, class Eq, class Hash, class Alloc >
0476     unordered_multimap_tag container_category(
0477         const std::unordered_multimap< Key, T, Eq, Hash, Alloc >&)
0478     {
0479         return unordered_multimap_tag();
0480     }
0481 #endif
0482 
0483 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET
0484     template < class Key, class Eq, class Hash, class Alloc >
0485     unstable_tag iterator_stability(
0486         const std::unordered_multiset< Key, Eq, Hash, Alloc >&)
0487     {
0488         return unstable_tag();
0489     }
0490 #endif
0491 
0492 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP
0493     template < class Key, class T, class Eq, class Hash, class Alloc >
0494     unstable_tag iterator_stability(
0495         const std::unordered_multimap< Key, T, Eq, Hash, Alloc >&)
0496     {
0497         return unstable_tag();
0498     }
0499 #endif
0500 
0501     //===========================================================================
0502     // Generalized Container Functions
0503 
0504     // Erase
0505     template < class Sequence, class T >
0506     void erase_dispatch(Sequence& c, const T& x, sequence_tag)
0507     {
0508         c.erase(std::remove(c.begin(), c.end(), x), c.end());
0509     }
0510 
0511     template < class AssociativeContainer, class T >
0512     void erase_dispatch(
0513         AssociativeContainer& c, const T& x, associative_container_tag)
0514     {
0515         c.erase(x);
0516     }
0517     template < class Container, class T > void erase(Container& c, const T& x)
0518     {
0519         erase_dispatch(c, x, container_category(c));
0520     }
0521 
0522     // Erase If
0523     template < class Sequence, class Predicate, class IteratorStability >
0524     void erase_if_dispatch(
0525         Sequence& c, Predicate p, sequence_tag, IteratorStability)
0526     {
0527 #if 0
0528     c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
0529 #else
0530         if (!c.empty())
0531             c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
0532 #endif
0533     }
0534     template < class AssociativeContainer, class Predicate >
0535     void erase_if_dispatch(AssociativeContainer& c, Predicate p,
0536         associative_container_tag, stable_tag)
0537     {
0538         typename AssociativeContainer::iterator i, next;
0539         for (i = next = c.begin(); next != c.end(); i = next)
0540         {
0541             ++next;
0542             if (p(*i))
0543                 c.erase(i);
0544         }
0545     }
0546     template < class AssociativeContainer, class Predicate >
0547     void erase_if_dispatch(AssociativeContainer& c, Predicate p,
0548         associative_container_tag, unstable_tag)
0549     {
0550         // This method is really slow, so hopefully we won't have any
0551         // associative containers with unstable iterators!
0552         // Is there a better way to do this?
0553         typename AssociativeContainer::iterator i;
0554         typename AssociativeContainer::size_type n = c.size();
0555         while (n--)
0556             for (i = c.begin(); i != c.end(); ++i)
0557                 if (p(*i))
0558                 {
0559                     c.erase(i);
0560                     break;
0561                 }
0562     }
0563     template < class Container, class Predicate >
0564     void erase_if(Container& c, Predicate p)
0565     {
0566         erase_if_dispatch(c, p, container_category(c), iterator_stability(c));
0567     }
0568 
0569     // Push
0570     template < class Container, class T >
0571     std::pair< typename Container::iterator, bool > push_dispatch(
0572         Container& c, BOOST_PENDING_FWD_TYPE(T) v, back_insertion_sequence_tag)
0573     {
0574         c.push_back(BOOST_PENDING_FWD_VALUE(T, v));
0575         return std::make_pair(boost::prior(c.end()), true);
0576     }
0577 
0578     template < class Container, class T >
0579     std::pair< typename Container::iterator, bool > push_dispatch(
0580         Container& c, BOOST_PENDING_FWD_TYPE(T) v, front_insertion_sequence_tag)
0581     {
0582         c.push_front(BOOST_PENDING_FWD_VALUE(T, v));
0583         return std::make_pair(c.begin(), true);
0584     }
0585 
0586     template < class AssociativeContainer, class T >
0587     std::pair< typename AssociativeContainer::iterator, bool > push_dispatch(
0588         AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v,
0589         unique_associative_container_tag)
0590     {
0591         return c.insert(BOOST_PENDING_FWD_VALUE(T, v));
0592     }
0593 
0594     template < class AssociativeContainer, class T >
0595     std::pair< typename AssociativeContainer::iterator, bool > push_dispatch(
0596         AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v,
0597         multiple_associative_container_tag)
0598     {
0599         return std::make_pair(c.insert(BOOST_PENDING_FWD_VALUE(T, v)), true);
0600     }
0601 
0602     template < class Container, class T >
0603     std::pair< typename Container::iterator, bool > push(
0604         Container& c, BOOST_PENDING_FWD_TYPE(T) v)
0605     {
0606         return push_dispatch(
0607             c, BOOST_PENDING_FWD_VALUE(T, v), container_category(c));
0608     }
0609 
0610     // Find
0611     template < class Container, class Value >
0612     typename Container::iterator find_dispatch(
0613         Container& c, const Value& value, container_tag)
0614     {
0615         return std::find(c.begin(), c.end(), value);
0616     }
0617 
0618     template < class AssociativeContainer, class Value >
0619     typename AssociativeContainer::iterator find_dispatch(
0620         AssociativeContainer& c, const Value& value, associative_container_tag)
0621     {
0622         return c.find(value);
0623     }
0624 
0625     template < class Container, class Value >
0626     typename Container::iterator find(Container& c, const Value& value)
0627     {
0628         return find_dispatch(c, value, graph_detail::container_category(c));
0629     }
0630 
0631     // Find (const versions)
0632     template < class Container, class Value >
0633     typename Container::const_iterator find_dispatch(
0634         const Container& c, const Value& value, container_tag)
0635     {
0636         return std::find(c.begin(), c.end(), value);
0637     }
0638 
0639     template < class AssociativeContainer, class Value >
0640     typename AssociativeContainer::const_iterator find_dispatch(
0641         const AssociativeContainer& c, const Value& value,
0642         associative_container_tag)
0643     {
0644         return c.find(value);
0645     }
0646 
0647     template < class Container, class Value >
0648     typename Container::const_iterator find(
0649         const Container& c, const Value& value)
0650     {
0651         return find_dispatch(c, value, graph_detail::container_category(c));
0652     }
0653 
0654     // Equal range
0655 #if 0
0656   // Make the dispatch fail if c is not an Associative Container (and thus
0657   // doesn't have equal_range unless it is sorted, which we cannot check
0658   // statically and is not typically true for BGL's uses of this function).
0659   template <class Container,
0660             class LessThanComparable>
0661   std::pair<typename Container::iterator, typename Container::iterator>
0662   equal_range_dispatch(Container& c,
0663                        const LessThanComparable& value,
0664                        container_tag)
0665   {
0666     // c must be sorted for std::equal_range to behave properly.
0667     return std::equal_range(c.begin(), c.end(), value);
0668   }
0669 #endif
0670 
0671     template < class AssociativeContainer, class Value >
0672     std::pair< typename AssociativeContainer::iterator,
0673         typename AssociativeContainer::iterator >
0674     equal_range_dispatch(
0675         AssociativeContainer& c, const Value& value, associative_container_tag)
0676     {
0677         return c.equal_range(value);
0678     }
0679 
0680     template < class Container, class Value >
0681     std::pair< typename Container::iterator, typename Container::iterator >
0682     equal_range(Container& c, const Value& value)
0683     {
0684         return equal_range_dispatch(
0685             c, value, graph_detail::container_category(c));
0686     }
0687 
0688 }
0689 } // namespace boost::graph_detail
0690 
0691 #undef BOOST_PENDING_FWD_TYPE
0692 #undef BOOST_PENDING_FWD_VALUE
0693 
0694 #endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H