composite_key.hpp 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513
  1. /* Copyright 2003-2015 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
  9. #define BOOST_MULTI_INDEX_COMPOSITE_KEY_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <boost/functional/hash_fwd.hpp>
  15. #include <boost/multi_index/detail/access_specifier.hpp>
  16. #include <boost/mpl/eval_if.hpp>
  17. #include <boost/mpl/identity.hpp>
  18. #include <boost/mpl/if.hpp>
  19. #include <boost/mpl/or.hpp>
  20. #include <boost/preprocessor/cat.hpp>
  21. #include <boost/preprocessor/control/expr_if.hpp>
  22. #include <boost/preprocessor/list/at.hpp>
  23. #include <boost/preprocessor/repetition/enum.hpp>
  24. #include <boost/preprocessor/repetition/enum_params.hpp>
  25. #include <boost/static_assert.hpp>
  26. #include <boost/tuple/tuple.hpp>
  27. #include <boost/type_traits/is_same.hpp>
  28. #include <boost/utility/enable_if.hpp>
  29. #include <functional>
  30. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  31. #include <boost/ref.hpp>
  32. #endif
  33. #if !defined(BOOST_NO_SFINAE)
  34. #include <boost/type_traits/is_convertible.hpp>
  35. #endif
  36. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
  37. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  38. #include <boost/multi_index/detail/cons_stdtuple.hpp>
  39. #endif
  40. /* A composite key stores n key extractors and "computes" the
  41. * result on a given value as a packed reference to the value and
  42. * the composite key itself. Actual invocations to the component
  43. * key extractors are lazily performed when executing an operation
  44. * on composite_key results (equality, comparison, hashing.)
  45. * As the other key extractors in Boost.MultiIndex, composite_key<T,...>
  46. * is overloaded to work on chained pointers to T and reference_wrappers
  47. * of T.
  48. */
  49. /* This user_definable macro limits the number of elements of a composite
  50. * key; useful for shortening resulting symbol names (MSVC++ 6.0, for
  51. * instance has problems coping with very long symbol names.)
  52. * NB: This cannot exceed the maximum number of arguments of
  53. * boost::tuple. In Boost 1.32, the limit is 10.
  54. */
  55. #if !defined(BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE)
  56. #define BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE 10
  57. #endif
  58. /* maximum number of key extractors in a composite key */
  59. #if BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE<10 /* max length of a tuple */
  60. #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE \
  61. BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE
  62. #else
  63. #define BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE 10
  64. #endif
  65. /* BOOST_PP_ENUM of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
  66. #define BOOST_MULTI_INDEX_CK_ENUM(macro,data) \
  67. BOOST_PP_ENUM(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,macro,data)
  68. /* BOOST_PP_ENUM_PARAMS of BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE elements */
  69. #define BOOST_MULTI_INDEX_CK_ENUM_PARAMS(param) \
  70. BOOST_PP_ENUM_PARAMS(BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE,param)
  71. /* if n==0 -> text0
  72. * otherwise -> textn=tuples::null_type
  73. */
  74. #define BOOST_MULTI_INDEX_CK_TEMPLATE_PARM(z,n,text) \
  75. typename BOOST_PP_CAT(text,n) BOOST_PP_EXPR_IF(n,=tuples::null_type)
  76. /* const textn& kn=textn() */
  77. #define BOOST_MULTI_INDEX_CK_CTOR_ARG(z,n,text) \
  78. const BOOST_PP_CAT(text,n)& BOOST_PP_CAT(k,n) = BOOST_PP_CAT(text,n)()
  79. /* typename list(0)<list(1),n>::type */
  80. #define BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N(z,n,list) \
  81. BOOST_DEDUCED_TYPENAME BOOST_PP_LIST_AT(list,0)< \
  82. BOOST_PP_LIST_AT(list,1),n \
  83. >::type
  84. namespace boost{
  85. template<class T> class reference_wrapper; /* fwd decl. */
  86. namespace multi_index{
  87. namespace detail{
  88. /* n-th key extractor of a composite key */
  89. template<typename CompositeKey,int N>
  90. struct nth_key_from_value
  91. {
  92. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  93. typedef typename mpl::eval_if_c<
  94. N<tuples::length<key_extractor_tuple>::value,
  95. tuples::element<N,key_extractor_tuple>,
  96. mpl::identity<tuples::null_type>
  97. >::type type;
  98. };
  99. /* nth_composite_key_##name<CompositeKey,N>::type yields
  100. * functor<nth_key_from_value<CompositeKey,N> >, or tuples::null_type
  101. * if N exceeds the length of the composite key.
  102. */
  103. #define BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(name,functor) \
  104. template<typename KeyFromValue> \
  105. struct BOOST_PP_CAT(key_,name) \
  106. { \
  107. typedef functor<typename KeyFromValue::result_type> type; \
  108. }; \
  109. \
  110. template<> \
  111. struct BOOST_PP_CAT(key_,name)<tuples::null_type> \
  112. { \
  113. typedef tuples::null_type type; \
  114. }; \
  115. \
  116. template<typename CompositeKey,int N> \
  117. struct BOOST_PP_CAT(nth_composite_key_,name) \
  118. { \
  119. typedef typename nth_key_from_value<CompositeKey,N>::type key_from_value; \
  120. typedef typename BOOST_PP_CAT(key_,name)<key_from_value>::type type; \
  121. };
  122. /* nth_composite_key_equal_to
  123. * nth_composite_key_less
  124. * nth_composite_key_greater
  125. * nth_composite_key_hash
  126. */
  127. BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(equal_to,std::equal_to)
  128. BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(less,std::less)
  129. BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(greater,std::greater)
  130. BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR(hash,boost::hash)
  131. /* used for defining equality and comparison ops of composite_key_result */
  132. #define BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO(z,n,text) text
  133. struct generic_operator_equal
  134. {
  135. template<typename T,typename Q>
  136. bool operator()(const T& x,const Q& y)const{return x==y;}
  137. };
  138. typedef tuple<
  139. BOOST_MULTI_INDEX_CK_ENUM(
  140. BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
  141. detail::generic_operator_equal)> generic_operator_equal_tuple;
  142. struct generic_operator_less
  143. {
  144. template<typename T,typename Q>
  145. bool operator()(const T& x,const Q& y)const{return x<y;}
  146. };
  147. typedef tuple<
  148. BOOST_MULTI_INDEX_CK_ENUM(
  149. BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO,
  150. detail::generic_operator_less)> generic_operator_less_tuple;
  151. /* Metaprogramming machinery for implementing equality, comparison and
  152. * hashing operations of composite_key_result.
  153. *
  154. * equal_* checks for equality between composite_key_results and
  155. * between those and tuples, accepting a tuple of basic equality functors.
  156. * compare_* does lexicographical comparison.
  157. * hash_* computes a combination of elementwise hash values.
  158. */
  159. template
  160. <
  161. typename KeyCons1,typename Value1,
  162. typename KeyCons2, typename Value2,
  163. typename EqualCons
  164. >
  165. struct equal_ckey_ckey; /* fwd decl. */
  166. template
  167. <
  168. typename KeyCons1,typename Value1,
  169. typename KeyCons2, typename Value2,
  170. typename EqualCons
  171. >
  172. struct equal_ckey_ckey_terminal
  173. {
  174. static bool compare(
  175. const KeyCons1&,const Value1&,
  176. const KeyCons2&,const Value2&,
  177. const EqualCons&)
  178. {
  179. return true;
  180. }
  181. };
  182. template
  183. <
  184. typename KeyCons1,typename Value1,
  185. typename KeyCons2, typename Value2,
  186. typename EqualCons
  187. >
  188. struct equal_ckey_ckey_normal
  189. {
  190. static bool compare(
  191. const KeyCons1& c0,const Value1& v0,
  192. const KeyCons2& c1,const Value2& v1,
  193. const EqualCons& eq)
  194. {
  195. if(!eq.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return false;
  196. return equal_ckey_ckey<
  197. BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
  198. BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
  199. BOOST_DEDUCED_TYPENAME EqualCons::tail_type
  200. >::compare(c0.get_tail(),v0,c1.get_tail(),v1,eq.get_tail());
  201. }
  202. };
  203. template
  204. <
  205. typename KeyCons1,typename Value1,
  206. typename KeyCons2, typename Value2,
  207. typename EqualCons
  208. >
  209. struct equal_ckey_ckey:
  210. mpl::if_<
  211. mpl::or_<
  212. is_same<KeyCons1,tuples::null_type>,
  213. is_same<KeyCons2,tuples::null_type>
  214. >,
  215. equal_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>,
  216. equal_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,EqualCons>
  217. >::type
  218. {
  219. };
  220. template
  221. <
  222. typename KeyCons,typename Value,
  223. typename ValCons,typename EqualCons
  224. >
  225. struct equal_ckey_cval; /* fwd decl. */
  226. template
  227. <
  228. typename KeyCons,typename Value,
  229. typename ValCons,typename EqualCons
  230. >
  231. struct equal_ckey_cval_terminal
  232. {
  233. static bool compare(
  234. const KeyCons&,const Value&,const ValCons&,const EqualCons&)
  235. {
  236. return true;
  237. }
  238. static bool compare(
  239. const ValCons&,const KeyCons&,const Value&,const EqualCons&)
  240. {
  241. return true;
  242. }
  243. };
  244. template
  245. <
  246. typename KeyCons,typename Value,
  247. typename ValCons,typename EqualCons
  248. >
  249. struct equal_ckey_cval_normal
  250. {
  251. static bool compare(
  252. const KeyCons& c,const Value& v,const ValCons& vc,
  253. const EqualCons& eq)
  254. {
  255. if(!eq.get_head()(c.get_head()(v),vc.get_head()))return false;
  256. return equal_ckey_cval<
  257. BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
  258. BOOST_DEDUCED_TYPENAME ValCons::tail_type,
  259. BOOST_DEDUCED_TYPENAME EqualCons::tail_type
  260. >::compare(c.get_tail(),v,vc.get_tail(),eq.get_tail());
  261. }
  262. static bool compare(
  263. const ValCons& vc,const KeyCons& c,const Value& v,
  264. const EqualCons& eq)
  265. {
  266. if(!eq.get_head()(vc.get_head(),c.get_head()(v)))return false;
  267. return equal_ckey_cval<
  268. BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
  269. BOOST_DEDUCED_TYPENAME ValCons::tail_type,
  270. BOOST_DEDUCED_TYPENAME EqualCons::tail_type
  271. >::compare(vc.get_tail(),c.get_tail(),v,eq.get_tail());
  272. }
  273. };
  274. template
  275. <
  276. typename KeyCons,typename Value,
  277. typename ValCons,typename EqualCons
  278. >
  279. struct equal_ckey_cval:
  280. mpl::if_<
  281. mpl::or_<
  282. is_same<KeyCons,tuples::null_type>,
  283. is_same<ValCons,tuples::null_type>
  284. >,
  285. equal_ckey_cval_terminal<KeyCons,Value,ValCons,EqualCons>,
  286. equal_ckey_cval_normal<KeyCons,Value,ValCons,EqualCons>
  287. >::type
  288. {
  289. };
  290. template
  291. <
  292. typename KeyCons1,typename Value1,
  293. typename KeyCons2, typename Value2,
  294. typename CompareCons
  295. >
  296. struct compare_ckey_ckey; /* fwd decl. */
  297. template
  298. <
  299. typename KeyCons1,typename Value1,
  300. typename KeyCons2, typename Value2,
  301. typename CompareCons
  302. >
  303. struct compare_ckey_ckey_terminal
  304. {
  305. static bool compare(
  306. const KeyCons1&,const Value1&,
  307. const KeyCons2&,const Value2&,
  308. const CompareCons&)
  309. {
  310. return false;
  311. }
  312. };
  313. template
  314. <
  315. typename KeyCons1,typename Value1,
  316. typename KeyCons2, typename Value2,
  317. typename CompareCons
  318. >
  319. struct compare_ckey_ckey_normal
  320. {
  321. static bool compare(
  322. const KeyCons1& c0,const Value1& v0,
  323. const KeyCons2& c1,const Value2& v1,
  324. const CompareCons& comp)
  325. {
  326. if(comp.get_head()(c0.get_head()(v0),c1.get_head()(v1)))return true;
  327. if(comp.get_head()(c1.get_head()(v1),c0.get_head()(v0)))return false;
  328. return compare_ckey_ckey<
  329. BOOST_DEDUCED_TYPENAME KeyCons1::tail_type,Value1,
  330. BOOST_DEDUCED_TYPENAME KeyCons2::tail_type,Value2,
  331. BOOST_DEDUCED_TYPENAME CompareCons::tail_type
  332. >::compare(c0.get_tail(),v0,c1.get_tail(),v1,comp.get_tail());
  333. }
  334. };
  335. template
  336. <
  337. typename KeyCons1,typename Value1,
  338. typename KeyCons2, typename Value2,
  339. typename CompareCons
  340. >
  341. struct compare_ckey_ckey:
  342. mpl::if_<
  343. mpl::or_<
  344. is_same<KeyCons1,tuples::null_type>,
  345. is_same<KeyCons2,tuples::null_type>
  346. >,
  347. compare_ckey_ckey_terminal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>,
  348. compare_ckey_ckey_normal<KeyCons1,Value1,KeyCons2,Value2,CompareCons>
  349. >::type
  350. {
  351. };
  352. template
  353. <
  354. typename KeyCons,typename Value,
  355. typename ValCons,typename CompareCons
  356. >
  357. struct compare_ckey_cval; /* fwd decl. */
  358. template
  359. <
  360. typename KeyCons,typename Value,
  361. typename ValCons,typename CompareCons
  362. >
  363. struct compare_ckey_cval_terminal
  364. {
  365. static bool compare(
  366. const KeyCons&,const Value&,const ValCons&,const CompareCons&)
  367. {
  368. return false;
  369. }
  370. static bool compare(
  371. const ValCons&,const KeyCons&,const Value&,const CompareCons&)
  372. {
  373. return false;
  374. }
  375. };
  376. template
  377. <
  378. typename KeyCons,typename Value,
  379. typename ValCons,typename CompareCons
  380. >
  381. struct compare_ckey_cval_normal
  382. {
  383. static bool compare(
  384. const KeyCons& c,const Value& v,const ValCons& vc,
  385. const CompareCons& comp)
  386. {
  387. if(comp.get_head()(c.get_head()(v),vc.get_head()))return true;
  388. if(comp.get_head()(vc.get_head(),c.get_head()(v)))return false;
  389. return compare_ckey_cval<
  390. BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
  391. BOOST_DEDUCED_TYPENAME ValCons::tail_type,
  392. BOOST_DEDUCED_TYPENAME CompareCons::tail_type
  393. >::compare(c.get_tail(),v,vc.get_tail(),comp.get_tail());
  394. }
  395. static bool compare(
  396. const ValCons& vc,const KeyCons& c,const Value& v,
  397. const CompareCons& comp)
  398. {
  399. if(comp.get_head()(vc.get_head(),c.get_head()(v)))return true;
  400. if(comp.get_head()(c.get_head()(v),vc.get_head()))return false;
  401. return compare_ckey_cval<
  402. BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
  403. BOOST_DEDUCED_TYPENAME ValCons::tail_type,
  404. BOOST_DEDUCED_TYPENAME CompareCons::tail_type
  405. >::compare(vc.get_tail(),c.get_tail(),v,comp.get_tail());
  406. }
  407. };
  408. template
  409. <
  410. typename KeyCons,typename Value,
  411. typename ValCons,typename CompareCons
  412. >
  413. struct compare_ckey_cval:
  414. mpl::if_<
  415. mpl::or_<
  416. is_same<KeyCons,tuples::null_type>,
  417. is_same<ValCons,tuples::null_type>
  418. >,
  419. compare_ckey_cval_terminal<KeyCons,Value,ValCons,CompareCons>,
  420. compare_ckey_cval_normal<KeyCons,Value,ValCons,CompareCons>
  421. >::type
  422. {
  423. };
  424. template<typename KeyCons,typename Value,typename HashCons>
  425. struct hash_ckey; /* fwd decl. */
  426. template<typename KeyCons,typename Value,typename HashCons>
  427. struct hash_ckey_terminal
  428. {
  429. static std::size_t hash(
  430. const KeyCons&,const Value&,const HashCons&,std::size_t carry)
  431. {
  432. return carry;
  433. }
  434. };
  435. template<typename KeyCons,typename Value,typename HashCons>
  436. struct hash_ckey_normal
  437. {
  438. static std::size_t hash(
  439. const KeyCons& c,const Value& v,const HashCons& h,std::size_t carry=0)
  440. {
  441. /* same hashing formula as boost::hash_combine */
  442. carry^=h.get_head()(c.get_head()(v))+0x9e3779b9+(carry<<6)+(carry>>2);
  443. return hash_ckey<
  444. BOOST_DEDUCED_TYPENAME KeyCons::tail_type,Value,
  445. BOOST_DEDUCED_TYPENAME HashCons::tail_type
  446. >::hash(c.get_tail(),v,h.get_tail(),carry);
  447. }
  448. };
  449. template<typename KeyCons,typename Value,typename HashCons>
  450. struct hash_ckey:
  451. mpl::if_<
  452. is_same<KeyCons,tuples::null_type>,
  453. hash_ckey_terminal<KeyCons,Value,HashCons>,
  454. hash_ckey_normal<KeyCons,Value,HashCons>
  455. >::type
  456. {
  457. };
  458. template<typename ValCons,typename HashCons>
  459. struct hash_cval; /* fwd decl. */
  460. template<typename ValCons,typename HashCons>
  461. struct hash_cval_terminal
  462. {
  463. static std::size_t hash(const ValCons&,const HashCons&,std::size_t carry)
  464. {
  465. return carry;
  466. }
  467. };
  468. template<typename ValCons,typename HashCons>
  469. struct hash_cval_normal
  470. {
  471. static std::size_t hash(
  472. const ValCons& vc,const HashCons& h,std::size_t carry=0)
  473. {
  474. carry^=h.get_head()(vc.get_head())+0x9e3779b9+(carry<<6)+(carry>>2);
  475. return hash_cval<
  476. BOOST_DEDUCED_TYPENAME ValCons::tail_type,
  477. BOOST_DEDUCED_TYPENAME HashCons::tail_type
  478. >::hash(vc.get_tail(),h.get_tail(),carry);
  479. }
  480. };
  481. template<typename ValCons,typename HashCons>
  482. struct hash_cval:
  483. mpl::if_<
  484. is_same<ValCons,tuples::null_type>,
  485. hash_cval_terminal<ValCons,HashCons>,
  486. hash_cval_normal<ValCons,HashCons>
  487. >::type
  488. {
  489. };
  490. } /* namespace multi_index::detail */
  491. /* composite_key_result */
  492. #if defined(BOOST_MSVC)
  493. #pragma warning(push)
  494. #pragma warning(disable:4512)
  495. #endif
  496. template<typename CompositeKey>
  497. struct composite_key_result
  498. {
  499. typedef CompositeKey composite_key_type;
  500. typedef typename composite_key_type::value_type value_type;
  501. composite_key_result(
  502. const composite_key_type& composite_key_,const value_type& value_):
  503. composite_key(composite_key_),value(value_)
  504. {}
  505. const composite_key_type& composite_key;
  506. const value_type& value;
  507. };
  508. #if defined(BOOST_MSVC)
  509. #pragma warning(pop)
  510. #endif
  511. /* composite_key */
  512. template<
  513. typename Value,
  514. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,KeyFromValue)
  515. >
  516. struct composite_key:
  517. private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)>
  518. {
  519. private:
  520. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(KeyFromValue)> super;
  521. public:
  522. typedef super key_extractor_tuple;
  523. typedef Value value_type;
  524. typedef composite_key_result<composite_key> result_type;
  525. composite_key(
  526. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,KeyFromValue)):
  527. super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
  528. {}
  529. composite_key(const key_extractor_tuple& x):super(x){}
  530. const key_extractor_tuple& key_extractors()const{return *this;}
  531. key_extractor_tuple& key_extractors(){return *this;}
  532. template<typename ChainedPtr>
  533. #if !defined(BOOST_NO_SFINAE)
  534. typename disable_if<
  535. is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
  536. #else
  537. result_type
  538. #endif
  539. operator()(const ChainedPtr& x)const
  540. {
  541. return operator()(*x);
  542. }
  543. result_type operator()(const value_type& x)const
  544. {
  545. return result_type(*this,x);
  546. }
  547. result_type operator()(const reference_wrapper<const value_type>& x)const
  548. {
  549. return result_type(*this,x.get());
  550. }
  551. result_type operator()(const reference_wrapper<value_type>& x)const
  552. {
  553. return result_type(*this,x.get());
  554. }
  555. };
  556. /* comparison operators */
  557. /* == */
  558. template<typename CompositeKey1,typename CompositeKey2>
  559. inline bool operator==(
  560. const composite_key_result<CompositeKey1>& x,
  561. const composite_key_result<CompositeKey2>& y)
  562. {
  563. typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
  564. typedef typename CompositeKey1::value_type value_type1;
  565. typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
  566. typedef typename CompositeKey2::value_type value_type2;
  567. BOOST_STATIC_ASSERT(
  568. tuples::length<key_extractor_tuple1>::value==
  569. tuples::length<key_extractor_tuple2>::value);
  570. return detail::equal_ckey_ckey<
  571. key_extractor_tuple1,value_type1,
  572. key_extractor_tuple2,value_type2,
  573. detail::generic_operator_equal_tuple
  574. >::compare(
  575. x.composite_key.key_extractors(),x.value,
  576. y.composite_key.key_extractors(),y.value,
  577. detail::generic_operator_equal_tuple());
  578. }
  579. template<
  580. typename CompositeKey,
  581. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
  582. >
  583. inline bool operator==(
  584. const composite_key_result<CompositeKey>& x,
  585. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
  586. {
  587. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  588. typedef typename CompositeKey::value_type value_type;
  589. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  590. BOOST_STATIC_ASSERT(
  591. tuples::length<key_extractor_tuple>::value==
  592. tuples::length<key_tuple>::value);
  593. return detail::equal_ckey_cval<
  594. key_extractor_tuple,value_type,
  595. key_tuple,detail::generic_operator_equal_tuple
  596. >::compare(
  597. x.composite_key.key_extractors(),x.value,
  598. y,detail::generic_operator_equal_tuple());
  599. }
  600. template
  601. <
  602. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
  603. typename CompositeKey
  604. >
  605. inline bool operator==(
  606. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
  607. const composite_key_result<CompositeKey>& y)
  608. {
  609. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  610. typedef typename CompositeKey::value_type value_type;
  611. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  612. BOOST_STATIC_ASSERT(
  613. tuples::length<key_extractor_tuple>::value==
  614. tuples::length<key_tuple>::value);
  615. return detail::equal_ckey_cval<
  616. key_extractor_tuple,value_type,
  617. key_tuple,detail::generic_operator_equal_tuple
  618. >::compare(
  619. x,y.composite_key.key_extractors(),
  620. y.value,detail::generic_operator_equal_tuple());
  621. }
  622. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
  623. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  624. template<typename CompositeKey,typename... Values>
  625. inline bool operator==(
  626. const composite_key_result<CompositeKey>& x,
  627. const std::tuple<Values...>& y)
  628. {
  629. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  630. typedef typename CompositeKey::value_type value_type;
  631. typedef std::tuple<Values...> key_tuple;
  632. typedef typename detail::cons_stdtuple_ctor<
  633. key_tuple>::result_type cons_key_tuple;
  634. BOOST_STATIC_ASSERT(
  635. static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
  636. std::tuple_size<key_tuple>::value);
  637. return detail::equal_ckey_cval<
  638. key_extractor_tuple,value_type,
  639. cons_key_tuple,detail::generic_operator_equal_tuple
  640. >::compare(
  641. x.composite_key.key_extractors(),x.value,
  642. detail::make_cons_stdtuple(y),detail::generic_operator_equal_tuple());
  643. }
  644. template<typename CompositeKey,typename... Values>
  645. inline bool operator==(
  646. const std::tuple<Values...>& x,
  647. const composite_key_result<CompositeKey>& y)
  648. {
  649. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  650. typedef typename CompositeKey::value_type value_type;
  651. typedef std::tuple<Values...> key_tuple;
  652. typedef typename detail::cons_stdtuple_ctor<
  653. key_tuple>::result_type cons_key_tuple;
  654. BOOST_STATIC_ASSERT(
  655. static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
  656. std::tuple_size<key_tuple>::value);
  657. return detail::equal_ckey_cval<
  658. key_extractor_tuple,value_type,
  659. cons_key_tuple,detail::generic_operator_equal_tuple
  660. >::compare(
  661. detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
  662. y.value,detail::generic_operator_equal_tuple());
  663. }
  664. #endif
  665. /* < */
  666. template<typename CompositeKey1,typename CompositeKey2>
  667. inline bool operator<(
  668. const composite_key_result<CompositeKey1>& x,
  669. const composite_key_result<CompositeKey2>& y)
  670. {
  671. typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
  672. typedef typename CompositeKey1::value_type value_type1;
  673. typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
  674. typedef typename CompositeKey2::value_type value_type2;
  675. return detail::compare_ckey_ckey<
  676. key_extractor_tuple1,value_type1,
  677. key_extractor_tuple2,value_type2,
  678. detail::generic_operator_less_tuple
  679. >::compare(
  680. x.composite_key.key_extractors(),x.value,
  681. y.composite_key.key_extractors(),y.value,
  682. detail::generic_operator_less_tuple());
  683. }
  684. template
  685. <
  686. typename CompositeKey,
  687. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
  688. >
  689. inline bool operator<(
  690. const composite_key_result<CompositeKey>& x,
  691. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)
  692. {
  693. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  694. typedef typename CompositeKey::value_type value_type;
  695. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  696. return detail::compare_ckey_cval<
  697. key_extractor_tuple,value_type,
  698. key_tuple,detail::generic_operator_less_tuple
  699. >::compare(
  700. x.composite_key.key_extractors(),x.value,
  701. y,detail::generic_operator_less_tuple());
  702. }
  703. template
  704. <
  705. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
  706. typename CompositeKey
  707. >
  708. inline bool operator<(
  709. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
  710. const composite_key_result<CompositeKey>& y)
  711. {
  712. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  713. typedef typename CompositeKey::value_type value_type;
  714. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  715. return detail::compare_ckey_cval<
  716. key_extractor_tuple,value_type,
  717. key_tuple,detail::generic_operator_less_tuple
  718. >::compare(
  719. x,y.composite_key.key_extractors(),
  720. y.value,detail::generic_operator_less_tuple());
  721. }
  722. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
  723. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  724. template<typename CompositeKey,typename... Values>
  725. inline bool operator<(
  726. const composite_key_result<CompositeKey>& x,
  727. const std::tuple<Values...>& y)
  728. {
  729. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  730. typedef typename CompositeKey::value_type value_type;
  731. typedef std::tuple<Values...> key_tuple;
  732. typedef typename detail::cons_stdtuple_ctor<
  733. key_tuple>::result_type cons_key_tuple;
  734. return detail::compare_ckey_cval<
  735. key_extractor_tuple,value_type,
  736. cons_key_tuple,detail::generic_operator_less_tuple
  737. >::compare(
  738. x.composite_key.key_extractors(),x.value,
  739. detail::make_cons_stdtuple(y),detail::generic_operator_less_tuple());
  740. }
  741. template<typename CompositeKey,typename... Values>
  742. inline bool operator<(
  743. const std::tuple<Values...>& x,
  744. const composite_key_result<CompositeKey>& y)
  745. {
  746. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  747. typedef typename CompositeKey::value_type value_type;
  748. typedef std::tuple<Values...> key_tuple;
  749. typedef typename detail::cons_stdtuple_ctor<
  750. key_tuple>::result_type cons_key_tuple;
  751. return detail::compare_ckey_cval<
  752. key_extractor_tuple,value_type,
  753. cons_key_tuple,detail::generic_operator_less_tuple
  754. >::compare(
  755. detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
  756. y.value,detail::generic_operator_less_tuple());
  757. }
  758. #endif
  759. /* rest of comparison operators */
  760. #define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2) \
  761. template<t1,t2> inline bool operator!=(const a1& x,const a2& y) \
  762. { \
  763. return !(x==y); \
  764. } \
  765. \
  766. template<t1,t2> inline bool operator>(const a1& x,const a2& y) \
  767. { \
  768. return y<x; \
  769. } \
  770. \
  771. template<t1,t2> inline bool operator>=(const a1& x,const a2& y) \
  772. { \
  773. return !(x<y); \
  774. } \
  775. \
  776. template<t1,t2> inline bool operator<=(const a1& x,const a2& y) \
  777. { \
  778. return !(y<x); \
  779. }
  780. BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
  781. typename CompositeKey1,
  782. typename CompositeKey2,
  783. composite_key_result<CompositeKey1>,
  784. composite_key_result<CompositeKey2>
  785. )
  786. BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
  787. typename CompositeKey,
  788. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
  789. composite_key_result<CompositeKey>,
  790. tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>
  791. )
  792. BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
  793. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
  794. typename CompositeKey,
  795. tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>,
  796. composite_key_result<CompositeKey>
  797. )
  798. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
  799. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  800. BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
  801. typename CompositeKey,
  802. typename... Values,
  803. composite_key_result<CompositeKey>,
  804. std::tuple<Values...>
  805. )
  806. BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
  807. typename CompositeKey,
  808. typename... Values,
  809. std::tuple<Values...>,
  810. composite_key_result<CompositeKey>
  811. )
  812. #endif
  813. /* composite_key_equal_to */
  814. template
  815. <
  816. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Pred)
  817. >
  818. struct composite_key_equal_to:
  819. private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)>
  820. {
  821. private:
  822. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Pred)> super;
  823. public:
  824. typedef super key_eq_tuple;
  825. composite_key_equal_to(
  826. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Pred)):
  827. super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
  828. {}
  829. composite_key_equal_to(const key_eq_tuple& x):super(x){}
  830. const key_eq_tuple& key_eqs()const{return *this;}
  831. key_eq_tuple& key_eqs(){return *this;}
  832. template<typename CompositeKey1,typename CompositeKey2>
  833. bool operator()(
  834. const composite_key_result<CompositeKey1> & x,
  835. const composite_key_result<CompositeKey2> & y)const
  836. {
  837. typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
  838. typedef typename CompositeKey1::value_type value_type1;
  839. typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
  840. typedef typename CompositeKey2::value_type value_type2;
  841. BOOST_STATIC_ASSERT(
  842. tuples::length<key_extractor_tuple1>::value<=
  843. tuples::length<key_eq_tuple>::value&&
  844. tuples::length<key_extractor_tuple1>::value==
  845. tuples::length<key_extractor_tuple2>::value);
  846. return detail::equal_ckey_ckey<
  847. key_extractor_tuple1,value_type1,
  848. key_extractor_tuple2,value_type2,
  849. key_eq_tuple
  850. >::compare(
  851. x.composite_key.key_extractors(),x.value,
  852. y.composite_key.key_extractors(),y.value,
  853. key_eqs());
  854. }
  855. template
  856. <
  857. typename CompositeKey,
  858. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
  859. >
  860. bool operator()(
  861. const composite_key_result<CompositeKey>& x,
  862. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
  863. {
  864. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  865. typedef typename CompositeKey::value_type value_type;
  866. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  867. BOOST_STATIC_ASSERT(
  868. tuples::length<key_extractor_tuple>::value<=
  869. tuples::length<key_eq_tuple>::value&&
  870. tuples::length<key_extractor_tuple>::value==
  871. tuples::length<key_tuple>::value);
  872. return detail::equal_ckey_cval<
  873. key_extractor_tuple,value_type,
  874. key_tuple,key_eq_tuple
  875. >::compare(x.composite_key.key_extractors(),x.value,y,key_eqs());
  876. }
  877. template
  878. <
  879. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
  880. typename CompositeKey
  881. >
  882. bool operator()(
  883. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
  884. const composite_key_result<CompositeKey>& y)const
  885. {
  886. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  887. typedef typename CompositeKey::value_type value_type;
  888. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  889. BOOST_STATIC_ASSERT(
  890. tuples::length<key_tuple>::value<=
  891. tuples::length<key_eq_tuple>::value&&
  892. tuples::length<key_tuple>::value==
  893. tuples::length<key_extractor_tuple>::value);
  894. return detail::equal_ckey_cval<
  895. key_extractor_tuple,value_type,
  896. key_tuple,key_eq_tuple
  897. >::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
  898. }
  899. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
  900. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  901. template<typename CompositeKey,typename... Values>
  902. bool operator()(
  903. const composite_key_result<CompositeKey>& x,
  904. const std::tuple<Values...>& y)const
  905. {
  906. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  907. typedef typename CompositeKey::value_type value_type;
  908. typedef std::tuple<Values...> key_tuple;
  909. typedef typename detail::cons_stdtuple_ctor<
  910. key_tuple>::result_type cons_key_tuple;
  911. BOOST_STATIC_ASSERT(
  912. tuples::length<key_extractor_tuple>::value<=
  913. tuples::length<key_eq_tuple>::value&&
  914. static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value)==
  915. std::tuple_size<key_tuple>::value);
  916. return detail::equal_ckey_cval<
  917. key_extractor_tuple,value_type,
  918. cons_key_tuple,key_eq_tuple
  919. >::compare(
  920. x.composite_key.key_extractors(),x.value,
  921. detail::make_cons_stdtuple(y),key_eqs());
  922. }
  923. template<typename CompositeKey,typename... Values>
  924. bool operator()(
  925. const std::tuple<Values...>& x,
  926. const composite_key_result<CompositeKey>& y)const
  927. {
  928. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  929. typedef typename CompositeKey::value_type value_type;
  930. typedef std::tuple<Values...> key_tuple;
  931. typedef typename detail::cons_stdtuple_ctor<
  932. key_tuple>::result_type cons_key_tuple;
  933. BOOST_STATIC_ASSERT(
  934. std::tuple_size<key_tuple>::value<=
  935. static_cast<std::size_t>(tuples::length<key_eq_tuple>::value)&&
  936. std::tuple_size<key_tuple>::value==
  937. static_cast<std::size_t>(tuples::length<key_extractor_tuple>::value));
  938. return detail::equal_ckey_cval<
  939. key_extractor_tuple,value_type,
  940. cons_key_tuple,key_eq_tuple
  941. >::compare(
  942. detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
  943. y.value,key_eqs());
  944. }
  945. #endif
  946. };
  947. /* composite_key_compare */
  948. template
  949. <
  950. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Compare)
  951. >
  952. struct composite_key_compare:
  953. private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)>
  954. {
  955. private:
  956. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Compare)> super;
  957. public:
  958. typedef super key_comp_tuple;
  959. composite_key_compare(
  960. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Compare)):
  961. super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
  962. {}
  963. composite_key_compare(const key_comp_tuple& x):super(x){}
  964. const key_comp_tuple& key_comps()const{return *this;}
  965. key_comp_tuple& key_comps(){return *this;}
  966. template<typename CompositeKey1,typename CompositeKey2>
  967. bool operator()(
  968. const composite_key_result<CompositeKey1> & x,
  969. const composite_key_result<CompositeKey2> & y)const
  970. {
  971. typedef typename CompositeKey1::key_extractor_tuple key_extractor_tuple1;
  972. typedef typename CompositeKey1::value_type value_type1;
  973. typedef typename CompositeKey2::key_extractor_tuple key_extractor_tuple2;
  974. typedef typename CompositeKey2::value_type value_type2;
  975. BOOST_STATIC_ASSERT(
  976. tuples::length<key_extractor_tuple1>::value<=
  977. tuples::length<key_comp_tuple>::value||
  978. tuples::length<key_extractor_tuple2>::value<=
  979. tuples::length<key_comp_tuple>::value);
  980. return detail::compare_ckey_ckey<
  981. key_extractor_tuple1,value_type1,
  982. key_extractor_tuple2,value_type2,
  983. key_comp_tuple
  984. >::compare(
  985. x.composite_key.key_extractors(),x.value,
  986. y.composite_key.key_extractors(),y.value,
  987. key_comps());
  988. }
  989. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  990. template<typename CompositeKey,typename Value>
  991. bool operator()(
  992. const composite_key_result<CompositeKey>& x,
  993. const Value& y)const
  994. {
  995. return operator()(x,boost::make_tuple(boost::cref(y)));
  996. }
  997. #endif
  998. template
  999. <
  1000. typename CompositeKey,
  1001. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)
  1002. >
  1003. bool operator()(
  1004. const composite_key_result<CompositeKey>& x,
  1005. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& y)const
  1006. {
  1007. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  1008. typedef typename CompositeKey::value_type value_type;
  1009. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  1010. BOOST_STATIC_ASSERT(
  1011. tuples::length<key_extractor_tuple>::value<=
  1012. tuples::length<key_comp_tuple>::value||
  1013. tuples::length<key_tuple>::value<=
  1014. tuples::length<key_comp_tuple>::value);
  1015. return detail::compare_ckey_cval<
  1016. key_extractor_tuple,value_type,
  1017. key_tuple,key_comp_tuple
  1018. >::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
  1019. }
  1020. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  1021. template<typename Value,typename CompositeKey>
  1022. bool operator()(
  1023. const Value& x,
  1024. const composite_key_result<CompositeKey>& y)const
  1025. {
  1026. return operator()(boost::make_tuple(boost::cref(x)),y);
  1027. }
  1028. #endif
  1029. template
  1030. <
  1031. BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
  1032. typename CompositeKey
  1033. >
  1034. bool operator()(
  1035. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x,
  1036. const composite_key_result<CompositeKey>& y)const
  1037. {
  1038. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  1039. typedef typename CompositeKey::value_type value_type;
  1040. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  1041. BOOST_STATIC_ASSERT(
  1042. tuples::length<key_tuple>::value<=
  1043. tuples::length<key_comp_tuple>::value||
  1044. tuples::length<key_extractor_tuple>::value<=
  1045. tuples::length<key_comp_tuple>::value);
  1046. return detail::compare_ckey_cval<
  1047. key_extractor_tuple,value_type,
  1048. key_tuple,key_comp_tuple
  1049. >::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
  1050. }
  1051. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
  1052. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  1053. template<typename CompositeKey,typename... Values>
  1054. bool operator()(
  1055. const composite_key_result<CompositeKey>& x,
  1056. const std::tuple<Values...>& y)const
  1057. {
  1058. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  1059. typedef typename CompositeKey::value_type value_type;
  1060. typedef std::tuple<Values...> key_tuple;
  1061. typedef typename detail::cons_stdtuple_ctor<
  1062. key_tuple>::result_type cons_key_tuple;
  1063. BOOST_STATIC_ASSERT(
  1064. tuples::length<key_extractor_tuple>::value<=
  1065. tuples::length<key_comp_tuple>::value||
  1066. std::tuple_size<key_tuple>::value<=
  1067. static_cast<std::size_t>(tuples::length<key_comp_tuple>::value));
  1068. return detail::compare_ckey_cval<
  1069. key_extractor_tuple,value_type,
  1070. cons_key_tuple,key_comp_tuple
  1071. >::compare(
  1072. x.composite_key.key_extractors(),x.value,
  1073. detail::make_cons_stdtuple(y),key_comps());
  1074. }
  1075. template<typename CompositeKey,typename... Values>
  1076. bool operator()(
  1077. const std::tuple<Values...>& x,
  1078. const composite_key_result<CompositeKey>& y)const
  1079. {
  1080. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  1081. typedef typename CompositeKey::value_type value_type;
  1082. typedef std::tuple<Values...> key_tuple;
  1083. typedef typename detail::cons_stdtuple_ctor<
  1084. key_tuple>::result_type cons_key_tuple;
  1085. BOOST_STATIC_ASSERT(
  1086. std::tuple_size<key_tuple>::value<=
  1087. static_cast<std::size_t>(tuples::length<key_comp_tuple>::value)||
  1088. tuples::length<key_extractor_tuple>::value<=
  1089. tuples::length<key_comp_tuple>::value);
  1090. return detail::compare_ckey_cval<
  1091. key_extractor_tuple,value_type,
  1092. cons_key_tuple,key_comp_tuple
  1093. >::compare(
  1094. detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
  1095. y.value,key_comps());
  1096. }
  1097. #endif
  1098. };
  1099. /* composite_key_hash */
  1100. template
  1101. <
  1102. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_TEMPLATE_PARM,Hash)
  1103. >
  1104. struct composite_key_hash:
  1105. private tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)>
  1106. {
  1107. private:
  1108. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Hash)> super;
  1109. public:
  1110. typedef super key_hasher_tuple;
  1111. composite_key_hash(
  1112. BOOST_MULTI_INDEX_CK_ENUM(BOOST_MULTI_INDEX_CK_CTOR_ARG,Hash)):
  1113. super(BOOST_MULTI_INDEX_CK_ENUM_PARAMS(k))
  1114. {}
  1115. composite_key_hash(const key_hasher_tuple& x):super(x){}
  1116. const key_hasher_tuple& key_hash_functions()const{return *this;}
  1117. key_hasher_tuple& key_hash_functions(){return *this;}
  1118. template<typename CompositeKey>
  1119. std::size_t operator()(const composite_key_result<CompositeKey> & x)const
  1120. {
  1121. typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
  1122. typedef typename CompositeKey::value_type value_type;
  1123. BOOST_STATIC_ASSERT(
  1124. tuples::length<key_extractor_tuple>::value==
  1125. tuples::length<key_hasher_tuple>::value);
  1126. return detail::hash_ckey<
  1127. key_extractor_tuple,value_type,
  1128. key_hasher_tuple
  1129. >::hash(x.composite_key.key_extractors(),x.value,key_hash_functions());
  1130. }
  1131. template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
  1132. std::size_t operator()(
  1133. const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const
  1134. {
  1135. typedef tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)> key_tuple;
  1136. BOOST_STATIC_ASSERT(
  1137. tuples::length<key_tuple>::value==
  1138. tuples::length<key_hasher_tuple>::value);
  1139. return detail::hash_cval<
  1140. key_tuple,key_hasher_tuple
  1141. >::hash(x,key_hash_functions());
  1142. }
  1143. #if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
  1144. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  1145. template<typename... Values>
  1146. std::size_t operator()(const std::tuple<Values...>& x)const
  1147. {
  1148. typedef std::tuple<Values...> key_tuple;
  1149. typedef typename detail::cons_stdtuple_ctor<
  1150. key_tuple>::result_type cons_key_tuple;
  1151. BOOST_STATIC_ASSERT(
  1152. std::tuple_size<key_tuple>::value==
  1153. static_cast<std::size_t>(tuples::length<key_hasher_tuple>::value));
  1154. return detail::hash_cval<
  1155. cons_key_tuple,key_hasher_tuple
  1156. >::hash(detail::make_cons_stdtuple(x),key_hash_functions());
  1157. }
  1158. #endif
  1159. };
  1160. /* Instantiations of the former functors with "natural" basic components:
  1161. * composite_key_result_equal_to uses std::equal_to of the values.
  1162. * composite_key_result_less uses std::less.
  1163. * composite_key_result_greater uses std::greater.
  1164. * composite_key_result_hash uses boost::hash.
  1165. */
  1166. #define BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER \
  1167. composite_key_equal_to< \
  1168. BOOST_MULTI_INDEX_CK_ENUM( \
  1169. BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
  1170. /* the argument is a PP list */ \
  1171. (detail::nth_composite_key_equal_to, \
  1172. (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
  1173. BOOST_PP_NIL))) \
  1174. >
  1175. template<typename CompositeKeyResult>
  1176. struct composite_key_result_equal_to:
  1177. BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1178. BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
  1179. {
  1180. private:
  1181. typedef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER super;
  1182. public:
  1183. typedef CompositeKeyResult first_argument_type;
  1184. typedef first_argument_type second_argument_type;
  1185. typedef bool result_type;
  1186. using super::operator();
  1187. };
  1188. #define BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER \
  1189. composite_key_compare< \
  1190. BOOST_MULTI_INDEX_CK_ENUM( \
  1191. BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
  1192. /* the argument is a PP list */ \
  1193. (detail::nth_composite_key_less, \
  1194. (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
  1195. BOOST_PP_NIL))) \
  1196. >
  1197. template<typename CompositeKeyResult>
  1198. struct composite_key_result_less:
  1199. BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1200. BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
  1201. {
  1202. private:
  1203. typedef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER super;
  1204. public:
  1205. typedef CompositeKeyResult first_argument_type;
  1206. typedef first_argument_type second_argument_type;
  1207. typedef bool result_type;
  1208. using super::operator();
  1209. };
  1210. #define BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER \
  1211. composite_key_compare< \
  1212. BOOST_MULTI_INDEX_CK_ENUM( \
  1213. BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
  1214. /* the argument is a PP list */ \
  1215. (detail::nth_composite_key_greater, \
  1216. (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
  1217. BOOST_PP_NIL))) \
  1218. >
  1219. template<typename CompositeKeyResult>
  1220. struct composite_key_result_greater:
  1221. BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1222. BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
  1223. {
  1224. private:
  1225. typedef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER super;
  1226. public:
  1227. typedef CompositeKeyResult first_argument_type;
  1228. typedef first_argument_type second_argument_type;
  1229. typedef bool result_type;
  1230. using super::operator();
  1231. };
  1232. #define BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER \
  1233. composite_key_hash< \
  1234. BOOST_MULTI_INDEX_CK_ENUM( \
  1235. BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N, \
  1236. /* the argument is a PP list */ \
  1237. (detail::nth_composite_key_hash, \
  1238. (BOOST_DEDUCED_TYPENAME CompositeKeyResult::composite_key_type, \
  1239. BOOST_PP_NIL))) \
  1240. >
  1241. template<typename CompositeKeyResult>
  1242. struct composite_key_result_hash:
  1243. BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS
  1244. BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
  1245. {
  1246. private:
  1247. typedef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER super;
  1248. public:
  1249. typedef CompositeKeyResult argument_type;
  1250. typedef std::size_t result_type;
  1251. using super::operator();
  1252. };
  1253. } /* namespace multi_index */
  1254. } /* namespace boost */
  1255. /* Specializations of std::equal_to, std::less, std::greater and boost::hash
  1256. * for composite_key_results enabling interoperation with tuples of values.
  1257. */
  1258. namespace std{
  1259. template<typename CompositeKey>
  1260. struct equal_to<boost::multi_index::composite_key_result<CompositeKey> >:
  1261. boost::multi_index::composite_key_result_equal_to<
  1262. boost::multi_index::composite_key_result<CompositeKey>
  1263. >
  1264. {
  1265. };
  1266. template<typename CompositeKey>
  1267. struct less<boost::multi_index::composite_key_result<CompositeKey> >:
  1268. boost::multi_index::composite_key_result_less<
  1269. boost::multi_index::composite_key_result<CompositeKey>
  1270. >
  1271. {
  1272. };
  1273. template<typename CompositeKey>
  1274. struct greater<boost::multi_index::composite_key_result<CompositeKey> >:
  1275. boost::multi_index::composite_key_result_greater<
  1276. boost::multi_index::composite_key_result<CompositeKey>
  1277. >
  1278. {
  1279. };
  1280. } /* namespace std */
  1281. namespace boost{
  1282. template<typename CompositeKey>
  1283. struct hash<boost::multi_index::composite_key_result<CompositeKey> >:
  1284. boost::multi_index::composite_key_result_hash<
  1285. boost::multi_index::composite_key_result<CompositeKey>
  1286. >
  1287. {
  1288. };
  1289. } /* namespace boost */
  1290. #undef BOOST_MULTI_INDEX_CK_RESULT_HASH_SUPER
  1291. #undef BOOST_MULTI_INDEX_CK_RESULT_GREATER_SUPER
  1292. #undef BOOST_MULTI_INDEX_CK_RESULT_LESS_SUPER
  1293. #undef BOOST_MULTI_INDEX_CK_RESULT_EQUAL_TO_SUPER
  1294. #undef BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS
  1295. #undef BOOST_MULTI_INDEX_CK_IDENTITY_ENUM_MACRO
  1296. #undef BOOST_MULTI_INDEX_CK_NTH_COMPOSITE_KEY_FUNCTOR
  1297. #undef BOOST_MULTI_INDEX_CK_APPLY_METAFUNCTION_N
  1298. #undef BOOST_MULTI_INDEX_CK_CTOR_ARG
  1299. #undef BOOST_MULTI_INDEX_CK_TEMPLATE_PARM
  1300. #undef BOOST_MULTI_INDEX_CK_ENUM_PARAMS
  1301. #undef BOOST_MULTI_INDEX_CK_ENUM
  1302. #undef BOOST_MULTI_INDEX_COMPOSITE_KEY_SIZE
  1303. #endif