container_traits.hpp 21 KB

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