1 // (C) Copyright Jeremy Siek 2004 2 // (C) Copyright Thomas Claveirole 2010 3 // (C) Copyright Ignacy Gawedzki 2010 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H 9 #define BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H 10 11 // Sure would be nice to be able to forward declare these 12 // instead of pulling in all the headers. Too bad that 13 // is not legal. There ought to be a standard <stlfwd> header. -JGS 14 15 #include <boost/next_prior.hpp> 16 17 #include <algorithm> // for std::remove 18 #include <utility> 19 #include <vector> 20 #include <list> 21 #include <map> 22 #include <set> 23 #include <boost/unordered_set.hpp> 24 #include <boost/unordered_map.hpp> 25 26 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET 27 #include <unordered_set> 28 #endif 29 30 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP 31 #include <unordered_map> 32 #endif 33 34 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES 35 #define BOOST_PENDING_FWD_TYPE(type) const type& 36 #define BOOST_PENDING_FWD_VALUE(type, var) (var) 37 #else 38 #define BOOST_PENDING_FWD_TYPE(type) type&& 39 #define BOOST_PENDING_FWD_VALUE(type, var) (std::forward< type >((var))) 40 #endif 41 42 // The content of this file is in 'graph_detail' because otherwise 43 // there will be name clashes with 44 // sandbox/boost/sequence_algo/container_traits.hpp 45 // The 'detail' subnamespace will still cause problems. 46 namespace boost 47 { 48 namespace graph_detail 49 { 50 51 //====================================================================== 52 // Container Category Tags 53 // 54 // They use virtual inheritance because there are lots of 55 // inheritance diamonds. 56 57 struct container_tag 58 { 59 }; 60 struct forward_container_tag : virtual public container_tag 61 { 62 }; 63 struct reversible_container_tag : virtual public forward_container_tag 64 { 65 }; 66 struct random_access_container_tag : virtual public reversible_container_tag 67 { 68 }; 69 70 struct sequence_tag : virtual public forward_container_tag 71 { 72 }; 73 74 struct associative_container_tag : virtual public forward_container_tag 75 { 76 }; 77 78 struct sorted_associative_container_tag 79 : virtual public associative_container_tag, 80 virtual public reversible_container_tag 81 { 82 }; 83 84 struct front_insertion_sequence_tag : virtual public sequence_tag 85 { 86 }; 87 struct back_insertion_sequence_tag : virtual public sequence_tag 88 { 89 }; 90 91 struct unique_associative_container_tag 92 : virtual public associative_container_tag 93 { 94 }; 95 struct multiple_associative_container_tag 96 : virtual public associative_container_tag 97 { 98 }; 99 struct simple_associative_container_tag 100 : virtual public associative_container_tag 101 { 102 }; 103 struct pair_associative_container_tag 104 : virtual public associative_container_tag 105 { 106 }; 107 108 //====================================================================== 109 // Iterator Stability Tags 110 // 111 // Do mutating operations such as insert/erase/resize invalidate all 112 // outstanding iterators? 113 114 struct stable_tag 115 { 116 }; 117 struct unstable_tag 118 { 119 }; 120 121 //====================================================================== 122 // Container Traits Class and container_category() function 123 124 // don't use this unless there is partial specialization 125 template < class Container > struct container_traits 126 { 127 typedef typename Container::category category; 128 typedef typename Container::iterator_stability iterator_stability; 129 }; 130 131 // Use this as a compile-time assertion that X is stable require_stable(stable_tag)132 inline void require_stable(stable_tag) {} 133 134 // std::vector 135 struct vector_tag : virtual public random_access_container_tag, 136 virtual public back_insertion_sequence_tag 137 { 138 }; 139 140 template < class T, class Alloc > container_category(const std::vector<T,Alloc> &)141 vector_tag container_category(const std::vector< T, Alloc >&) 142 { 143 return vector_tag(); 144 } 145 146 template < class T, class Alloc > iterator_stability(const std::vector<T,Alloc> &)147 unstable_tag iterator_stability(const std::vector< T, Alloc >&) 148 { 149 return unstable_tag(); 150 } 151 152 template < class T, class Alloc > 153 struct container_traits< std::vector< T, Alloc > > 154 { 155 typedef vector_tag category; 156 typedef unstable_tag iterator_stability; 157 }; 158 159 // std::list 160 struct list_tag : virtual public reversible_container_tag, 161 virtual public back_insertion_sequence_tag 162 // this causes problems for push_dispatch... 163 // virtual public front_insertion_sequence_tag 164 { 165 }; 166 167 template < class T, class Alloc > container_category(const std::list<T,Alloc> &)168 list_tag container_category(const std::list< T, Alloc >&) 169 { 170 return list_tag(); 171 } 172 173 template < class T, class Alloc > iterator_stability(const std::list<T,Alloc> &)174 stable_tag iterator_stability(const std::list< T, Alloc >&) 175 { 176 return stable_tag(); 177 } 178 179 template < class T, class Alloc > 180 struct container_traits< std::list< T, Alloc > > 181 { 182 typedef list_tag category; 183 typedef stable_tag iterator_stability; 184 }; 185 186 // std::set 187 struct set_tag : virtual public sorted_associative_container_tag, 188 virtual public simple_associative_container_tag, 189 virtual public unique_associative_container_tag 190 { 191 }; 192 193 template < class Key, class Cmp, class Alloc > container_category(const std::set<Key,Cmp,Alloc> &)194 set_tag container_category(const std::set< Key, Cmp, Alloc >&) 195 { 196 return set_tag(); 197 } 198 199 template < class Key, class Cmp, class Alloc > iterator_stability(const std::set<Key,Cmp,Alloc> &)200 stable_tag iterator_stability(const std::set< Key, Cmp, Alloc >&) 201 { 202 return stable_tag(); 203 } 204 205 template < class Key, class Cmp, class Alloc > 206 struct container_traits< std::set< Key, Cmp, Alloc > > 207 { 208 typedef set_tag category; 209 typedef stable_tag iterator_stability; 210 }; 211 212 // std::multiset 213 struct multiset_tag : virtual public sorted_associative_container_tag, 214 virtual public simple_associative_container_tag, 215 virtual public multiple_associative_container_tag 216 { 217 }; 218 219 template < class Key, class Cmp, class Alloc > container_category(const std::multiset<Key,Cmp,Alloc> &)220 multiset_tag container_category(const std::multiset< Key, Cmp, Alloc >&) 221 { 222 return multiset_tag(); 223 } 224 225 template < class Key, class Cmp, class Alloc > iterator_stability(const std::multiset<Key,Cmp,Alloc> &)226 stable_tag iterator_stability(const std::multiset< Key, Cmp, Alloc >&) 227 { 228 return stable_tag(); 229 } 230 231 template < class Key, class Cmp, class Alloc > 232 struct container_traits< std::multiset< Key, Cmp, Alloc > > 233 { 234 typedef multiset_tag category; 235 typedef stable_tag iterator_stability; 236 }; 237 238 // deque 239 240 // std::map 241 struct map_tag : virtual public sorted_associative_container_tag, 242 virtual public pair_associative_container_tag, 243 virtual public unique_associative_container_tag 244 { 245 }; 246 247 template < class Key, class T, class Cmp, class Alloc > 248 struct container_traits< std::map< Key, T, Cmp, Alloc > > 249 { 250 typedef map_tag category; 251 typedef stable_tag iterator_stability; 252 }; 253 254 template < class Key, class T, class Cmp, class Alloc > container_category(const std::map<Key,T,Cmp,Alloc> &)255 map_tag container_category(const std::map< Key, T, Cmp, Alloc >&) 256 { 257 return map_tag(); 258 } 259 260 template < class Key, class T, class Cmp, class Alloc > iterator_stability(const std::map<Key,T,Cmp,Alloc> &)261 stable_tag iterator_stability(const std::map< Key, T, Cmp, Alloc >&) 262 { 263 return stable_tag(); 264 } 265 266 // std::multimap 267 struct multimap_tag : virtual public sorted_associative_container_tag, 268 virtual public pair_associative_container_tag, 269 virtual public multiple_associative_container_tag 270 { 271 }; 272 273 template < class Key, class T, class Cmp, class Alloc > 274 struct container_traits< std::multimap< Key, T, Cmp, Alloc > > 275 { 276 typedef multimap_tag category; 277 typedef stable_tag iterator_stability; 278 }; 279 280 template < class Key, class T, class Cmp, class Alloc > container_category(const std::multimap<Key,T,Cmp,Alloc> &)281 multimap_tag container_category(const std::multimap< Key, T, Cmp, Alloc >&) 282 { 283 return multimap_tag(); 284 } 285 286 template < class Key, class T, class Cmp, class Alloc > iterator_stability(const std::multimap<Key,T,Cmp,Alloc> &)287 stable_tag iterator_stability(const std::multimap< Key, T, Cmp, Alloc >&) 288 { 289 return stable_tag(); 290 } 291 292 // hash_set, hash_map 293 294 struct unordered_set_tag : virtual public simple_associative_container_tag, 295 virtual public unique_associative_container_tag 296 { 297 }; 298 299 struct unordered_multiset_tag 300 : virtual public simple_associative_container_tag, 301 virtual public multiple_associative_container_tag 302 { 303 }; 304 305 struct unordered_map_tag : virtual public pair_associative_container_tag, 306 virtual public unique_associative_container_tag 307 { 308 }; 309 310 struct unordered_multimap_tag 311 : virtual public pair_associative_container_tag, 312 virtual public multiple_associative_container_tag 313 { 314 }; 315 316 template < class Key, class Eq, class Hash, class Alloc > 317 struct container_traits< boost::unordered_set< Key, Eq, Hash, Alloc > > 318 { 319 typedef unordered_set_tag category; 320 typedef unstable_tag iterator_stability; 321 }; 322 template < class Key, class T, class Eq, class Hash, class Alloc > 323 struct container_traits< boost::unordered_map< Key, T, Eq, Hash, Alloc > > 324 { 325 typedef unordered_map_tag category; 326 typedef unstable_tag iterator_stability; 327 }; 328 template < class Key, class Eq, class Hash, class Alloc > 329 struct container_traits< boost::unordered_multiset< Key, Eq, Hash, Alloc > > 330 { 331 typedef unordered_multiset_tag category; 332 typedef unstable_tag iterator_stability; 333 }; 334 template < class Key, class T, class Eq, class Hash, class Alloc > 335 struct container_traits< 336 boost::unordered_multimap< Key, T, Eq, Hash, Alloc > > 337 { 338 typedef unordered_multimap_tag category; 339 typedef unstable_tag iterator_stability; 340 }; 341 342 template < class Key, class Eq, class Hash, class Alloc > container_category(const boost::unordered_set<Key,Eq,Hash,Alloc> &)343 unordered_set_tag container_category( 344 const boost::unordered_set< Key, Eq, Hash, Alloc >&) 345 { 346 return unordered_set_tag(); 347 } 348 349 template < class Key, class T, class Eq, class Hash, class Alloc > container_category(const boost::unordered_map<Key,T,Eq,Hash,Alloc> &)350 unordered_map_tag container_category( 351 const boost::unordered_map< Key, T, Eq, Hash, Alloc >&) 352 { 353 return unordered_map_tag(); 354 } 355 356 template < class Key, class Eq, class Hash, class Alloc > iterator_stability(const boost::unordered_set<Key,Eq,Hash,Alloc> &)357 unstable_tag iterator_stability( 358 const boost::unordered_set< Key, Eq, Hash, Alloc >&) 359 { 360 return unstable_tag(); 361 } 362 363 template < class Key, class T, class Eq, class Hash, class Alloc > iterator_stability(const boost::unordered_map<Key,T,Eq,Hash,Alloc> &)364 unstable_tag iterator_stability( 365 const boost::unordered_map< Key, T, Eq, Hash, Alloc >&) 366 { 367 return unstable_tag(); 368 } 369 template < class Key, class Eq, class Hash, class Alloc > container_category(const boost::unordered_multiset<Key,Eq,Hash,Alloc> &)370 unordered_multiset_tag container_category( 371 const boost::unordered_multiset< Key, Eq, Hash, Alloc >&) 372 { 373 return unordered_multiset_tag(); 374 } 375 376 template < class Key, class T, class Eq, class Hash, class Alloc > container_category(const boost::unordered_multimap<Key,T,Eq,Hash,Alloc> &)377 unordered_multimap_tag container_category( 378 const boost::unordered_multimap< Key, T, Eq, Hash, Alloc >&) 379 { 380 return unordered_multimap_tag(); 381 } 382 383 template < class Key, class Eq, class Hash, class Alloc > iterator_stability(const boost::unordered_multiset<Key,Eq,Hash,Alloc> &)384 unstable_tag iterator_stability( 385 const boost::unordered_multiset< Key, Eq, Hash, Alloc >&) 386 { 387 return unstable_tag(); 388 } 389 390 template < class Key, class T, class Eq, class Hash, class Alloc > iterator_stability(const boost::unordered_multimap<Key,T,Eq,Hash,Alloc> &)391 unstable_tag iterator_stability( 392 const boost::unordered_multimap< Key, T, Eq, Hash, Alloc >&) 393 { 394 return unstable_tag(); 395 } 396 397 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET 398 template < class Key, class Eq, class Hash, class Alloc > 399 struct container_traits< std::unordered_set< Key, Eq, Hash, Alloc > > 400 { 401 typedef unordered_set_tag category; 402 typedef unstable_tag iterator_stability; 403 }; 404 #endif 405 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP 406 template < class Key, class T, class Eq, class Hash, class Alloc > 407 struct container_traits< std::unordered_map< Key, T, Eq, Hash, Alloc > > 408 { 409 typedef unordered_map_tag category; 410 typedef unstable_tag iterator_stability; 411 }; 412 #endif 413 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET 414 template < class Key, class Eq, class Hash, class Alloc > 415 struct container_traits< std::unordered_multiset< Key, Eq, Hash, Alloc > > 416 { 417 typedef unordered_multiset_tag category; 418 typedef unstable_tag iterator_stability; 419 }; 420 #endif 421 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP 422 template < class Key, class T, class Eq, class Hash, class Alloc > 423 struct container_traits< 424 std::unordered_multimap< Key, T, Eq, Hash, Alloc > > 425 { 426 typedef unordered_multimap_tag category; 427 typedef unstable_tag iterator_stability; 428 }; 429 #endif 430 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET 431 template < class Key, class Eq, class Hash, class Alloc > container_category(const std::unordered_set<Key,Eq,Hash,Alloc> &)432 unordered_set_tag container_category( 433 const std::unordered_set< Key, Eq, Hash, Alloc >&) 434 { 435 return unordered_set_tag(); 436 } 437 #endif 438 439 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP 440 template < class Key, class T, class Eq, class Hash, class Alloc > container_category(const std::unordered_map<Key,T,Eq,Hash,Alloc> &)441 unordered_map_tag container_category( 442 const std::unordered_map< Key, T, Eq, Hash, Alloc >&) 443 { 444 return unordered_map_tag(); 445 } 446 #endif 447 448 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET 449 template < class Key, class Eq, class Hash, class Alloc > iterator_stability(const std::unordered_set<Key,Eq,Hash,Alloc> &)450 unstable_tag iterator_stability( 451 const std::unordered_set< Key, Eq, Hash, Alloc >&) 452 { 453 return unstable_tag(); 454 } 455 #endif 456 457 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP 458 template < class Key, class T, class Eq, class Hash, class Alloc > iterator_stability(const std::unordered_map<Key,T,Eq,Hash,Alloc> &)459 unstable_tag iterator_stability( 460 const std::unordered_map< Key, T, Eq, Hash, Alloc >&) 461 { 462 return unstable_tag(); 463 } 464 #endif 465 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET 466 template < class Key, class Eq, class Hash, class Alloc > container_category(const std::unordered_multiset<Key,Eq,Hash,Alloc> &)467 unordered_multiset_tag container_category( 468 const std::unordered_multiset< Key, Eq, Hash, Alloc >&) 469 { 470 return unordered_multiset_tag(); 471 } 472 #endif 473 474 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP 475 template < class Key, class T, class Eq, class Hash, class Alloc > container_category(const std::unordered_multimap<Key,T,Eq,Hash,Alloc> &)476 unordered_multimap_tag container_category( 477 const std::unordered_multimap< Key, T, Eq, Hash, Alloc >&) 478 { 479 return unordered_multimap_tag(); 480 } 481 #endif 482 483 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_SET 484 template < class Key, class Eq, class Hash, class Alloc > iterator_stability(const std::unordered_multiset<Key,Eq,Hash,Alloc> &)485 unstable_tag iterator_stability( 486 const std::unordered_multiset< Key, Eq, Hash, Alloc >&) 487 { 488 return unstable_tag(); 489 } 490 #endif 491 492 #ifndef BOOST_NO_CXX11_HDR_UNORDERED_MAP 493 template < class Key, class T, class Eq, class Hash, class Alloc > iterator_stability(const std::unordered_multimap<Key,T,Eq,Hash,Alloc> &)494 unstable_tag iterator_stability( 495 const std::unordered_multimap< Key, T, Eq, Hash, Alloc >&) 496 { 497 return unstable_tag(); 498 } 499 #endif 500 501 //=========================================================================== 502 // Generalized Container Functions 503 504 // Erase 505 template < class Sequence, class T > erase_dispatch(Sequence & c,const T & x,sequence_tag)506 void erase_dispatch(Sequence& c, const T& x, sequence_tag) 507 { 508 c.erase(std::remove(c.begin(), c.end(), x), c.end()); 509 } 510 511 template < class AssociativeContainer, class T > erase_dispatch(AssociativeContainer & c,const T & x,associative_container_tag)512 void erase_dispatch( 513 AssociativeContainer& c, const T& x, associative_container_tag) 514 { 515 c.erase(x); 516 } erase(Container & c,const T & x)517 template < class Container, class T > void erase(Container& c, const T& x) 518 { 519 erase_dispatch(c, x, container_category(c)); 520 } 521 522 // Erase If 523 template < class Sequence, class Predicate, class IteratorStability > erase_if_dispatch(Sequence & c,Predicate p,sequence_tag,IteratorStability)524 void erase_if_dispatch( 525 Sequence& c, Predicate p, sequence_tag, IteratorStability) 526 { 527 #if 0 528 c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); 529 #else 530 if (!c.empty()) 531 c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); 532 #endif 533 } 534 template < class AssociativeContainer, class Predicate > erase_if_dispatch(AssociativeContainer & c,Predicate p,associative_container_tag,stable_tag)535 void erase_if_dispatch(AssociativeContainer& c, Predicate p, 536 associative_container_tag, stable_tag) 537 { 538 typename AssociativeContainer::iterator i, next; 539 for (i = next = c.begin(); next != c.end(); i = next) 540 { 541 ++next; 542 if (p(*i)) 543 c.erase(i); 544 } 545 } 546 template < class AssociativeContainer, class Predicate > erase_if_dispatch(AssociativeContainer & c,Predicate p,associative_container_tag,unstable_tag)547 void erase_if_dispatch(AssociativeContainer& c, Predicate p, 548 associative_container_tag, unstable_tag) 549 { 550 // This method is really slow, so hopefully we won't have any 551 // associative containers with unstable iterators! 552 // Is there a better way to do this? 553 typename AssociativeContainer::iterator i; 554 typename AssociativeContainer::size_type n = c.size(); 555 while (n--) 556 for (i = c.begin(); i != c.end(); ++i) 557 if (p(*i)) 558 { 559 c.erase(i); 560 break; 561 } 562 } 563 template < class Container, class Predicate > erase_if(Container & c,Predicate p)564 void erase_if(Container& c, Predicate p) 565 { 566 erase_if_dispatch(c, p, container_category(c), iterator_stability(c)); 567 } 568 569 // Push 570 template < class Container, class T > push_dispatch(Container & c,BOOST_PENDING_FWD_TYPE (T)v,back_insertion_sequence_tag)571 std::pair< typename Container::iterator, bool > push_dispatch( 572 Container& c, BOOST_PENDING_FWD_TYPE(T) v, back_insertion_sequence_tag) 573 { 574 c.push_back(BOOST_PENDING_FWD_VALUE(T, v)); 575 return std::make_pair(boost::prior(c.end()), true); 576 } 577 578 template < class Container, class T > push_dispatch(Container & c,BOOST_PENDING_FWD_TYPE (T)v,front_insertion_sequence_tag)579 std::pair< typename Container::iterator, bool > push_dispatch( 580 Container& c, BOOST_PENDING_FWD_TYPE(T) v, front_insertion_sequence_tag) 581 { 582 c.push_front(BOOST_PENDING_FWD_VALUE(T, v)); 583 return std::make_pair(c.begin(), true); 584 } 585 586 template < class AssociativeContainer, class T > push_dispatch(AssociativeContainer & c,BOOST_PENDING_FWD_TYPE (T)v,unique_associative_container_tag)587 std::pair< typename AssociativeContainer::iterator, bool > push_dispatch( 588 AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v, 589 unique_associative_container_tag) 590 { 591 return c.insert(BOOST_PENDING_FWD_VALUE(T, v)); 592 } 593 594 template < class AssociativeContainer, class T > push_dispatch(AssociativeContainer & c,BOOST_PENDING_FWD_TYPE (T)v,multiple_associative_container_tag)595 std::pair< typename AssociativeContainer::iterator, bool > push_dispatch( 596 AssociativeContainer& c, BOOST_PENDING_FWD_TYPE(T) v, 597 multiple_associative_container_tag) 598 { 599 return std::make_pair(c.insert(BOOST_PENDING_FWD_VALUE(T, v)), true); 600 } 601 602 template < class Container, class T > push(Container & c,BOOST_PENDING_FWD_TYPE (T)v)603 std::pair< typename Container::iterator, bool > push( 604 Container& c, BOOST_PENDING_FWD_TYPE(T) v) 605 { 606 return push_dispatch( 607 c, BOOST_PENDING_FWD_VALUE(T, v), container_category(c)); 608 } 609 610 // Find 611 template < class Container, class Value > find_dispatch(Container & c,const Value & value,container_tag)612 typename Container::iterator find_dispatch( 613 Container& c, const Value& value, container_tag) 614 { 615 return std::find(c.begin(), c.end(), value); 616 } 617 618 template < class AssociativeContainer, class Value > find_dispatch(AssociativeContainer & c,const Value & value,associative_container_tag)619 typename AssociativeContainer::iterator find_dispatch( 620 AssociativeContainer& c, const Value& value, associative_container_tag) 621 { 622 return c.find(value); 623 } 624 625 template < class Container, class Value > find(Container & c,const Value & value)626 typename Container::iterator find(Container& c, const Value& value) 627 { 628 return find_dispatch(c, value, graph_detail::container_category(c)); 629 } 630 631 // Find (const versions) 632 template < class Container, class Value > find_dispatch(const Container & c,const Value & value,container_tag)633 typename Container::const_iterator find_dispatch( 634 const Container& c, const Value& value, container_tag) 635 { 636 return std::find(c.begin(), c.end(), value); 637 } 638 639 template < class AssociativeContainer, class Value > find_dispatch(const AssociativeContainer & c,const Value & value,associative_container_tag)640 typename AssociativeContainer::const_iterator find_dispatch( 641 const AssociativeContainer& c, const Value& value, 642 associative_container_tag) 643 { 644 return c.find(value); 645 } 646 647 template < class Container, class Value > find(const Container & c,const Value & value)648 typename Container::const_iterator find( 649 const Container& c, const Value& value) 650 { 651 return find_dispatch(c, value, graph_detail::container_category(c)); 652 } 653 654 // Equal range 655 #if 0 656 // Make the dispatch fail if c is not an Associative Container (and thus 657 // doesn't have equal_range unless it is sorted, which we cannot check 658 // statically and is not typically true for BGL's uses of this function). 659 template <class Container, 660 class LessThanComparable> 661 std::pair<typename Container::iterator, typename Container::iterator> 662 equal_range_dispatch(Container& c, 663 const LessThanComparable& value, 664 container_tag) 665 { 666 // c must be sorted for std::equal_range to behave properly. 667 return std::equal_range(c.begin(), c.end(), value); 668 } 669 #endif 670 671 template < class AssociativeContainer, class Value > 672 std::pair< typename AssociativeContainer::iterator, 673 typename AssociativeContainer::iterator > equal_range_dispatch(AssociativeContainer & c,const Value & value,associative_container_tag)674 equal_range_dispatch( 675 AssociativeContainer& c, const Value& value, associative_container_tag) 676 { 677 return c.equal_range(value); 678 } 679 680 template < class Container, class Value > 681 std::pair< typename Container::iterator, typename Container::iterator > equal_range(Container & c,const Value & value)682 equal_range(Container& c, const Value& value) 683 { 684 return equal_range_dispatch( 685 c, value, graph_detail::container_category(c)); 686 } 687 688 } 689 } // namespace boost::graph_detail 690 691 #undef BOOST_PENDING_FWD_TYPE 692 #undef BOOST_PENDING_FWD_VALUE 693 694 #endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H 695