map_view_base.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. // Boost.Bimap
  2. //
  3. // Copyright (c) 2006-2007 Matias Capeletto
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. /// \file detail/map_view_base.hpp
  9. /// \brief Helper base for the construction of the bimap views types.
  10. #ifndef BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP
  11. #define BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP
  12. #if defined(_MSC_VER)
  13. #pragma once
  14. #endif
  15. #include <boost/config.hpp>
  16. #include <stdexcept>
  17. #include <utility>
  18. #include <boost/throw_exception.hpp>
  19. #include <boost/type_traits/is_const.hpp>
  20. #include <boost/mpl/if.hpp>
  21. #include <boost/bimap/relation/support/get_pair_functor.hpp>
  22. #include <boost/bimap/relation/detail/to_mutable_relation_functor.hpp>
  23. #include <boost/bimap/container_adaptor/support/iterator_facade_converters.hpp>
  24. #include <boost/bimap/relation/support/data_extractor.hpp>
  25. #include <boost/bimap/relation/support/opposite_tag.hpp>
  26. #include <boost/bimap/relation/support/pair_type_by.hpp>
  27. //#include <boost/bimap/support/iterator_type_by.hpp>
  28. #include <boost/bimap/support/key_type_by.hpp>
  29. #include <boost/bimap/support/data_type_by.hpp>
  30. #include <boost/bimap/support/value_type_by.hpp>
  31. #include <boost/bimap/detail/modifier_adaptor.hpp>
  32. #include <boost/bimap/detail/debug/static_error.hpp>
  33. #include <boost/bimap/detail/map_view_iterator.hpp>
  34. namespace boost {
  35. namespace bimaps {
  36. namespace detail {
  37. // The next macro can be converted in a metafunctor to gain code robustness.
  38. /*===========================================================================*/
  39. #define BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( \
  40. CONTAINER_ADAPTOR, TAG, BIMAP, OTHER_ITER, CONST_OTHER_ITER \
  41. ) \
  42. ::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR \
  43. < \
  44. BOOST_DEDUCED_TYPENAME BIMAP::core_type:: \
  45. BOOST_NESTED_TEMPLATE index<TAG>::type, \
  46. ::boost::bimaps::detail:: map_view_iterator<TAG,BIMAP>, \
  47. ::boost::bimaps::detail::const_map_view_iterator<TAG,BIMAP>, \
  48. ::boost::bimaps::detail:: OTHER_ITER<TAG,BIMAP>, \
  49. ::boost::bimaps::detail::CONST_OTHER_ITER<TAG,BIMAP>, \
  50. ::boost::bimaps::container_adaptor::support::iterator_facade_to_base \
  51. < \
  52. ::boost::bimaps::detail:: map_view_iterator<TAG,BIMAP>, \
  53. ::boost::bimaps::detail::const_map_view_iterator<TAG,BIMAP> \
  54. >, \
  55. ::boost::mpl::na, \
  56. ::boost::mpl::na, \
  57. ::boost::bimaps::relation::detail:: \
  58. pair_to_relation_functor<TAG,BOOST_DEDUCED_TYPENAME BIMAP::relation>, \
  59. ::boost::bimaps::relation::support:: \
  60. get_pair_functor<TAG, BOOST_DEDUCED_TYPENAME BIMAP::relation > \
  61. >
  62. /*===========================================================================*/
  63. #if defined(BOOST_MSVC)
  64. /*===========================================================================*/
  65. #define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \
  66. typedef ::boost::bimaps::detail::map_view_base< \
  67. TYPE<TAG,BIMAP>,TAG,BIMAP > friend_map_view_base; \
  68. friend class friend_map_view_base;
  69. /*===========================================================================*/
  70. #else
  71. /*===========================================================================*/
  72. #define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \
  73. friend class ::boost::bimaps::detail::map_view_base< \
  74. TYPE<TAG,BIMAP>,TAG,BIMAP >;
  75. /*===========================================================================*/
  76. #endif
  77. /// \brief Common base for map views.
  78. template< class Derived, class Tag, class BimapType>
  79. class map_view_base
  80. {
  81. typedef ::boost::bimaps::container_adaptor::support::
  82. iterator_facade_to_base<
  83. ::boost::bimaps::detail:: map_view_iterator<Tag,BimapType>,
  84. ::boost::bimaps::detail::const_map_view_iterator<Tag,BimapType>
  85. > iterator_to_base_;
  86. typedef ::boost::bimaps::relation::detail::
  87. pair_to_relation_functor<Tag,
  88. BOOST_DEDUCED_TYPENAME BimapType::relation> value_to_base_;
  89. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
  90. key_type_by<Tag,BimapType>::type key_type_;
  91. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
  92. data_type_by<Tag,BimapType>::type data_type_;
  93. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
  94. pair_type_by<Tag,
  95. BOOST_DEDUCED_TYPENAME BimapType::relation>::type value_type_;
  96. typedef
  97. ::boost::bimaps::detail::map_view_iterator<Tag,BimapType> iterator_;
  98. public:
  99. bool replace(iterator_ position, const value_type_ & x)
  100. {
  101. return derived().base().replace(
  102. derived().template functor<iterator_to_base_>()(position),
  103. derived().template functor<value_to_base_>()(x)
  104. );
  105. }
  106. template< class CompatibleKey >
  107. bool replace_key(iterator_ position, const CompatibleKey & k)
  108. {
  109. return derived().base().replace(
  110. derived().template functor<iterator_to_base_>()(position),
  111. derived().template functor<value_to_base_>()(
  112. ::boost::bimaps::relation::detail::
  113. copy_with_first_replaced(*position,k)
  114. )
  115. );
  116. }
  117. template< class CompatibleData >
  118. bool replace_data(iterator_ position, const CompatibleData & d)
  119. {
  120. return derived().base().replace(
  121. derived().template functor<iterator_to_base_>()(position),
  122. derived().template functor<value_to_base_>()(
  123. ::boost::bimaps::relation::detail::
  124. copy_with_second_replaced(*position,d)
  125. )
  126. );
  127. }
  128. /* This function may be provided in the future
  129. template< class Modifier >
  130. bool modify(iterator_ position, Modifier mod)
  131. {
  132. return derived().base().modify(
  133. derived().template functor<iterator_to_base_>()(position),
  134. ::boost::bimaps::detail::relation_modifier_adaptor
  135. <
  136. Modifier,
  137. BOOST_DEDUCED_TYPENAME BimapType::relation,
  138. BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
  139. data_extractor
  140. <
  141. Tag, BOOST_DEDUCED_TYPENAME BimapType::relation
  142. >::type,
  143. BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
  144. data_extractor
  145. <
  146. BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
  147. opossite_tag<Tag,BimapType>::type,
  148. BOOST_DEDUCED_TYPENAME BimapType::relation
  149. >::type
  150. >(mod)
  151. );
  152. }
  153. */
  154. template< class Modifier >
  155. bool modify_key(iterator_ position, Modifier mod)
  156. {
  157. return derived().base().modify_key(
  158. derived().template functor<iterator_to_base_>()(position), mod
  159. );
  160. }
  161. template< class Modifier >
  162. bool modify_data(iterator_ position, Modifier mod)
  163. {
  164. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
  165. data_extractor
  166. <
  167. BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::
  168. opossite_tag<Tag,BimapType>::type,
  169. BOOST_DEDUCED_TYPENAME BimapType::relation
  170. >::type data_extractor_;
  171. return derived().base().modify(
  172. derived().template functor<iterator_to_base_>()(position),
  173. // this may be replaced later by
  174. // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) )
  175. ::boost::bimaps::detail::unary_modifier_adaptor
  176. <
  177. Modifier,
  178. BOOST_DEDUCED_TYPENAME BimapType::relation,
  179. data_extractor_
  180. >(mod)
  181. );
  182. }
  183. protected:
  184. typedef map_view_base map_view_base_;
  185. private:
  186. // Curiously Recurring Template interface.
  187. Derived& derived()
  188. {
  189. return *static_cast<Derived*>(this);
  190. }
  191. Derived const& derived() const
  192. {
  193. return *static_cast<Derived const*>(this);
  194. }
  195. };
  196. template< class Derived, class Tag, class BimapType>
  197. class mutable_data_unique_map_view_access
  198. {
  199. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
  200. data_type_by<Tag,BimapType>::type data_type_;
  201. public:
  202. template< class CompatibleKey >
  203. data_type_ & at(const CompatibleKey& k)
  204. {
  205. typedef ::boost::bimaps::detail::
  206. map_view_iterator<Tag,BimapType> iterator;
  207. iterator iter = derived().find(k);
  208. if( iter == derived().end() )
  209. {
  210. ::boost::throw_exception(
  211. std::out_of_range("bimap<>: invalid key")
  212. );
  213. }
  214. return iter->second;
  215. }
  216. template< class CompatibleKey >
  217. const data_type_ & at(const CompatibleKey& k) const
  218. {
  219. typedef ::boost::bimaps::detail::
  220. const_map_view_iterator<Tag,BimapType> const_iterator;
  221. const_iterator iter = derived().find(k);
  222. if( iter == derived().end() )
  223. {
  224. ::boost::throw_exception(
  225. std::out_of_range("bimap<>: invalid key")
  226. );
  227. }
  228. return iter->second;
  229. }
  230. template< class CompatibleKey >
  231. data_type_ & operator[](const CompatibleKey& k)
  232. {
  233. typedef ::boost::bimaps::detail::
  234. map_view_iterator<Tag,BimapType> iterator;
  235. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
  236. value_type_by<Tag,BimapType>::type value_type;
  237. iterator iter = derived().find(k);
  238. if( iter == derived().end() )
  239. {
  240. iter = derived().insert( value_type(k,data_type_()) ).first;
  241. }
  242. return iter->second;
  243. }
  244. protected:
  245. typedef mutable_data_unique_map_view_access
  246. mutable_data_unique_map_view_access_;
  247. private:
  248. // Curiously Recurring Template interface.
  249. Derived& derived()
  250. {
  251. return *static_cast<Derived*>(this);
  252. }
  253. Derived const& derived() const
  254. {
  255. return *static_cast<Derived const*>(this);
  256. }
  257. };
  258. template< class Derived, class Tag, class BimapType>
  259. class non_mutable_data_unique_map_view_access
  260. {
  261. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
  262. data_type_by<Tag,BimapType>::type data_type_;
  263. public:
  264. template< class CompatibleKey >
  265. const data_type_ & at(const CompatibleKey& k) const
  266. {
  267. typedef ::boost::bimaps::detail::
  268. const_map_view_iterator<Tag,BimapType> const_iterator;
  269. const_iterator iter = derived().find(k);
  270. if( iter == derived().end() )
  271. {
  272. ::boost::throw_exception(
  273. std::out_of_range("bimap<>: invalid key")
  274. );
  275. }
  276. return iter->second;
  277. }
  278. template< class CompatibleKey >
  279. data_type_ & operator[](const CompatibleKey&)
  280. {
  281. BOOST_BIMAP_STATIC_ERROR( OPERATOR_BRACKET_IS_NOT_SUPPORTED, (Derived));
  282. }
  283. protected:
  284. typedef non_mutable_data_unique_map_view_access
  285. non_mutable_data_unique_map_view_access_;
  286. private:
  287. // Curiously Recurring Template interface.
  288. Derived& derived()
  289. {
  290. return *static_cast<Derived*>(this);
  291. }
  292. Derived const& derived() const
  293. {
  294. return *static_cast<Derived const*>(this);
  295. }
  296. };
  297. template< class Derived, class Tag, class BimapType>
  298. struct unique_map_view_access
  299. {
  300. private:
  301. typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::
  302. value_type_by<Tag,BimapType>::type value_type;
  303. public:
  304. typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_
  305. <
  306. typename ::boost::is_const<
  307. BOOST_DEDUCED_TYPENAME value_type::second_type >::type,
  308. non_mutable_data_unique_map_view_access<Derived,Tag,BimapType>,
  309. mutable_data_unique_map_view_access<Derived,Tag,BimapType>
  310. >::type type;
  311. };
  312. // Map views specialize the following structs to provide to the bimap class
  313. // the extra side typedefs (i.e. left_local_iterator for unordered_maps,
  314. // right_range_type for maps)
  315. template< class MapView >
  316. struct left_map_view_extra_typedefs {};
  317. template< class MapView >
  318. struct right_map_view_extra_typedefs {};
  319. } // namespace detail
  320. // This function is already part of Boost.Lambda.
  321. // They may be moved to Boost.Utility.
  322. template <class T> inline const T& make_const(const T& t) { return t; }
  323. } // namespace bimaps
  324. } // namespace boost
  325. // The following macros avoids code duplication in map views
  326. // Maybe this can be changed in the future using a scheme similar to
  327. // the one used with map_view_base.
  328. /*===========================================================================*/
  329. #define BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(BASE) \
  330. \
  331. typedef std::pair< \
  332. BOOST_DEDUCED_TYPENAME base_::iterator, \
  333. BOOST_DEDUCED_TYPENAME base_::iterator> range_type; \
  334. \
  335. typedef std::pair< \
  336. BOOST_DEDUCED_TYPENAME base_::const_iterator, \
  337. BOOST_DEDUCED_TYPENAME base_::const_iterator> const_range_type; \
  338. \
  339. \
  340. template< class LowerBounder, class UpperBounder> \
  341. range_type range(LowerBounder lower,UpperBounder upper) \
  342. { \
  343. std::pair< \
  344. \
  345. BOOST_DEDUCED_TYPENAME BASE::base_type::iterator, \
  346. BOOST_DEDUCED_TYPENAME BASE::base_type::iterator \
  347. \
  348. > r( this->base().range(lower,upper) ); \
  349. \
  350. return range_type( \
  351. this->template functor< \
  352. BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \
  353. >() ( r.first ), \
  354. this->template functor< \
  355. BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \
  356. >() ( r.second ) \
  357. ); \
  358. } \
  359. \
  360. template< class LowerBounder, class UpperBounder> \
  361. const_range_type range(LowerBounder lower,UpperBounder upper) const \
  362. { \
  363. std::pair< \
  364. \
  365. BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator, \
  366. BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator \
  367. \
  368. > r( this->base().range(lower,upper) ); \
  369. \
  370. return const_range_type( \
  371. this->template functor< \
  372. BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \
  373. >() ( r.first ), \
  374. this->template functor< \
  375. BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \
  376. >() ( r.second ) \
  377. ); \
  378. }
  379. /*===========================================================================*/
  380. /*===========================================================================*/
  381. #define BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(BASE) \
  382. \
  383. template< class InputIterator > \
  384. void assign(InputIterator first,InputIterator last) \
  385. { \
  386. this->clear(); \
  387. this->insert(this->end(),first,last); \
  388. } \
  389. \
  390. void assign(BOOST_DEDUCED_TYPENAME BASE::size_type n, \
  391. const BOOST_DEDUCED_TYPENAME BASE::value_type& v) \
  392. { \
  393. this->clear(); \
  394. for(BOOST_DEDUCED_TYPENAME BASE::size_type i = 0 ; i < n ; ++i) \
  395. { \
  396. this->push_back(v); \
  397. } \
  398. }
  399. /*===========================================================================*/
  400. /*===========================================================================*/
  401. #define BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(BASE) \
  402. \
  403. BOOST_DEDUCED_TYPENAME BASE::reference front() \
  404. { \
  405. return this->template functor< \
  406. BOOST_DEDUCED_TYPENAME base_::value_from_base>() \
  407. ( \
  408. const_cast \
  409. < \
  410. BOOST_DEDUCED_TYPENAME BASE::base_type::value_type & \
  411. \
  412. > ( this->base().front() ) \
  413. ); \
  414. } \
  415. \
  416. BOOST_DEDUCED_TYPENAME BASE::reference back() \
  417. { \
  418. return this->template functor< \
  419. BOOST_DEDUCED_TYPENAME base_::value_from_base>() \
  420. ( \
  421. const_cast \
  422. < \
  423. BOOST_DEDUCED_TYPENAME BASE::base_type::value_type & \
  424. \
  425. >( this->base().back() ) \
  426. ); \
  427. } \
  428. \
  429. BOOST_DEDUCED_TYPENAME BASE::const_reference front() const \
  430. { \
  431. return this->template functor< \
  432. BOOST_DEDUCED_TYPENAME BASE::value_from_base>() \
  433. ( \
  434. this->base().front() \
  435. ); \
  436. } \
  437. \
  438. BOOST_DEDUCED_TYPENAME BASE::const_reference back() const \
  439. { \
  440. return this->template functor< \
  441. BOOST_DEDUCED_TYPENAME BASE::value_from_base>() \
  442. ( \
  443. this->base().back() \
  444. ); \
  445. }
  446. /*===========================================================================*/
  447. #endif // BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP