tuple_basic.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. // tuple_basic.hpp -----------------------------------------------------
  2. // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
  3. //
  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. // For more information, see http://www.boost.org
  8. // Outside help:
  9. // This and that, Gary Powell.
  10. // Fixed return types for get_head/get_tail
  11. // ( and other bugs ) per suggestion of Jens Maurer
  12. // simplified element type accessors + bug fix (Jeremy Siek)
  13. // Several changes/additions according to suggestions by Douglas Gregor,
  14. // William Kempf, Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes,
  15. // David Abrahams.
  16. // Revision history:
  17. // 2002 05 01 Hugo Duncan: Fix for Borland after Jaakko's previous changes
  18. // 2002 04 18 Jaakko: tuple element types can be void or plain function
  19. // types, as long as no object is created.
  20. // Tuple objects can no hold even noncopyable types
  21. // such as arrays.
  22. // 2001 10 22 John Maddock
  23. // Fixes for Borland C++
  24. // 2001 08 30 David Abrahams
  25. // Added default constructor for cons<>.
  26. // -----------------------------------------------------------------
  27. #ifndef BOOST_TUPLE_BASIC_HPP
  28. #define BOOST_TUPLE_BASIC_HPP
  29. #include <utility> // needed for the assignment from pair to tuple
  30. #include <cstddef> // for std::size_t
  31. #include <boost/core/invoke_swap.hpp>
  32. #include <boost/type_traits/cv_traits.hpp>
  33. #include <boost/type_traits/function_traits.hpp>
  34. #include <boost/type_traits/integral_constant.hpp>
  35. #include <boost/detail/workaround.hpp> // needed for BOOST_WORKAROUND
  36. #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  37. #pragma GCC diagnostic push
  38. #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
  39. #endif
  40. namespace boost {
  41. namespace tuples {
  42. // -- null_type --------------------------------------------------------
  43. struct null_type {};
  44. // a helper function to provide a const null_type type temporary
  45. namespace detail {
  46. inline const null_type cnull() { return null_type(); }
  47. // -- if construct ------------------------------------------------
  48. // Proposed by Krzysztof Czarnecki and Ulrich Eisenecker
  49. template <bool If, class Then, class Else> struct IF { typedef Then RET; };
  50. template <class Then, class Else> struct IF<false, Then, Else> {
  51. typedef Else RET;
  52. };
  53. } // end detail
  54. // - cons forward declaration -----------------------------------------------
  55. template <class HT, class TT> struct cons;
  56. // - tuple forward declaration -----------------------------------------------
  57. template <
  58. class T0 = null_type, class T1 = null_type, class T2 = null_type,
  59. class T3 = null_type, class T4 = null_type, class T5 = null_type,
  60. class T6 = null_type, class T7 = null_type, class T8 = null_type,
  61. class T9 = null_type>
  62. class tuple;
  63. // tuple_length forward declaration
  64. template<class T> struct length;
  65. namespace detail {
  66. // -- generate error template, referencing to non-existing members of this
  67. // template is used to produce compilation errors intentionally
  68. template<class T>
  69. class generate_error;
  70. template<std::size_t N>
  71. struct drop_front {
  72. template<class Tuple>
  73. struct apply {
  74. typedef BOOST_DEDUCED_TYPENAME drop_front<N-1>::BOOST_NESTED_TEMPLATE
  75. apply<Tuple> next;
  76. typedef BOOST_DEDUCED_TYPENAME next::type::tail_type type;
  77. static const type& call(const Tuple& tup) {
  78. return next::call(tup).tail;
  79. }
  80. };
  81. };
  82. template<>
  83. struct drop_front<0> {
  84. template<class Tuple>
  85. struct apply {
  86. typedef Tuple type;
  87. static const type& call(const Tuple& tup) {
  88. return tup;
  89. }
  90. };
  91. };
  92. } // end of namespace detail
  93. // -cons type accessors ----------------------------------------
  94. // typename tuples::element<N,T>::type gets the type of the
  95. // Nth element ot T, first element is at index 0
  96. // -------------------------------------------------------
  97. #ifndef BOOST_NO_CV_SPECIALIZATIONS
  98. template<std::size_t N, class T>
  99. struct element
  100. {
  101. typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
  102. apply<T>::type::head_type type;
  103. };
  104. template<std::size_t N, class T>
  105. struct element<N, const T>
  106. {
  107. private:
  108. typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
  109. apply<T>::type::head_type unqualified_type;
  110. public:
  111. #if BOOST_WORKAROUND(BOOST_BORLANDC,<0x600)
  112. typedef const unqualified_type type;
  113. #else
  114. typedef BOOST_DEDUCED_TYPENAME boost::add_const<unqualified_type>::type type;
  115. #endif
  116. };
  117. #else // def BOOST_NO_CV_SPECIALIZATIONS
  118. namespace detail {
  119. template<std::size_t N, class T, bool IsConst>
  120. struct element_impl
  121. {
  122. typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
  123. apply<T>::type::head_type type;
  124. };
  125. template<std::size_t N, class T>
  126. struct element_impl<N, T, true /* IsConst */>
  127. {
  128. typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
  129. apply<T>::type::head_type unqualified_type;
  130. typedef const unqualified_type type;
  131. };
  132. } // end of namespace detail
  133. template<std::size_t N, class T>
  134. struct element:
  135. public detail::element_impl<N, T, ::boost::is_const<T>::value>
  136. {
  137. };
  138. #endif
  139. // -get function templates -----------------------------------------------
  140. // Usage: get<N>(aTuple)
  141. // -- some traits classes for get functions
  142. // access traits lifted from detail namespace to be part of the interface,
  143. // (Joel de Guzman's suggestion). Rationale: get functions are part of the
  144. // interface, so should the way to express their return types be.
  145. template <class T> struct access_traits {
  146. typedef const T& const_type;
  147. typedef T& non_const_type;
  148. typedef const typename boost::remove_cv<T>::type& parameter_type;
  149. // used as the tuple constructors parameter types
  150. // Rationale: non-reference tuple element types can be cv-qualified.
  151. // It should be possible to initialize such types with temporaries,
  152. // and when binding temporaries to references, the reference must
  153. // be non-volatile and const. 8.5.3. (5)
  154. };
  155. template <class T> struct access_traits<T&> {
  156. typedef T& const_type;
  157. typedef T& non_const_type;
  158. typedef T& parameter_type;
  159. };
  160. // get function for non-const cons-lists, returns a reference to the element
  161. template<std::size_t N, class HT, class TT>
  162. inline typename access_traits<
  163. typename element<N, cons<HT, TT> >::type
  164. >::non_const_type
  165. get(cons<HT, TT>& c) {
  166. typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
  167. apply<cons<HT, TT> > impl;
  168. typedef BOOST_DEDUCED_TYPENAME impl::type cons_element;
  169. return const_cast<cons_element&>(impl::call(c)).head;
  170. }
  171. // get function for const cons-lists, returns a const reference to
  172. // the element. If the element is a reference, returns the reference
  173. // as such (that is, can return a non-const reference)
  174. template<std::size_t N, class HT, class TT>
  175. inline typename access_traits<
  176. typename element<N, cons<HT, TT> >::type
  177. >::const_type
  178. get(const cons<HT, TT>& c) {
  179. typedef BOOST_DEDUCED_TYPENAME detail::drop_front<N>::BOOST_NESTED_TEMPLATE
  180. apply<cons<HT, TT> > impl;
  181. return impl::call(c).head;
  182. }
  183. // -- the cons template --------------------------------------------------
  184. namespace detail {
  185. // These helper templates wrap void types and plain function types.
  186. // The reationale is to allow one to write tuple types with those types
  187. // as elements, even though it is not possible to instantiate such object.
  188. // E.g: typedef tuple<void> some_type; // ok
  189. // but: some_type x; // fails
  190. template <class T> class non_storeable_type {
  191. non_storeable_type();
  192. };
  193. template <class T> struct wrap_non_storeable_type {
  194. typedef typename IF<
  195. ::boost::is_function<T>::value, non_storeable_type<T>, T
  196. >::RET type;
  197. };
  198. template <> struct wrap_non_storeable_type<void> {
  199. typedef non_storeable_type<void> type;
  200. };
  201. } // detail
  202. template <class HT, class TT>
  203. struct cons {
  204. typedef HT head_type;
  205. typedef TT tail_type;
  206. typedef typename
  207. detail::wrap_non_storeable_type<head_type>::type stored_head_type;
  208. stored_head_type head;
  209. tail_type tail;
  210. typename access_traits<stored_head_type>::non_const_type
  211. get_head() { return head; }
  212. typename access_traits<tail_type>::non_const_type
  213. get_tail() { return tail; }
  214. typename access_traits<stored_head_type>::const_type
  215. get_head() const { return head; }
  216. typename access_traits<tail_type>::const_type
  217. get_tail() const { return tail; }
  218. cons() : head(), tail() {}
  219. // cons() : head(detail::default_arg<HT>::f()), tail() {}
  220. // the argument for head is not strictly needed, but it prevents
  221. // array type elements. This is good, since array type elements
  222. // cannot be supported properly in any case (no assignment,
  223. // copy works only if the tails are exactly the same type, ...)
  224. cons(typename access_traits<stored_head_type>::parameter_type h,
  225. const tail_type& t)
  226. : head (h), tail(t) {}
  227. template <class T1, class T2, class T3, class T4, class T5,
  228. class T6, class T7, class T8, class T9, class T10>
  229. cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5,
  230. T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 )
  231. : head (t1),
  232. tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull())
  233. {}
  234. template <class T2, class T3, class T4, class T5,
  235. class T6, class T7, class T8, class T9, class T10>
  236. cons( const null_type& /*t1*/, T2& t2, T3& t3, T4& t4, T5& t5,
  237. T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 )
  238. : head (),
  239. tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull())
  240. {}
  241. cons( const cons& u ) : head(u.head), tail(u.tail) {}
  242. template <class HT2, class TT2>
  243. cons( const cons<HT2, TT2>& u ) : head(u.head), tail(u.tail) {}
  244. template <class HT2, class TT2>
  245. cons& operator=( const cons<HT2, TT2>& u ) {
  246. head=u.head; tail=u.tail; return *this;
  247. }
  248. // must define assignment operator explicitly, implicit version is
  249. // illformed if HT is a reference (12.8. (12))
  250. cons& operator=(const cons& u) {
  251. head = u.head; tail = u.tail; return *this;
  252. }
  253. template <class T1, class T2>
  254. cons& operator=( const std::pair<T1, T2>& u ) {
  255. BOOST_STATIC_ASSERT(length<cons>::value == 2); // check length = 2
  256. head = u.first; tail.head = u.second; return *this;
  257. }
  258. // get member functions (non-const and const)
  259. template <std::size_t N>
  260. typename access_traits<
  261. typename element<N, cons<HT, TT> >::type
  262. >::non_const_type
  263. get() {
  264. return boost::tuples::get<N>(*this); // delegate to non-member get
  265. }
  266. template <std::size_t N>
  267. typename access_traits<
  268. typename element<N, cons<HT, TT> >::type
  269. >::const_type
  270. get() const {
  271. return boost::tuples::get<N>(*this); // delegate to non-member get
  272. }
  273. };
  274. template <class HT>
  275. struct cons<HT, null_type> {
  276. typedef HT head_type;
  277. typedef null_type tail_type;
  278. typedef cons<HT, null_type> self_type;
  279. typedef typename
  280. detail::wrap_non_storeable_type<head_type>::type stored_head_type;
  281. stored_head_type head;
  282. typename access_traits<stored_head_type>::non_const_type
  283. get_head() { return head; }
  284. null_type get_tail() { return null_type(); }
  285. typename access_traits<stored_head_type>::const_type
  286. get_head() const { return head; }
  287. const null_type get_tail() const { return null_type(); }
  288. // cons() : head(detail::default_arg<HT>::f()) {}
  289. cons() : head() {}
  290. cons(typename access_traits<stored_head_type>::parameter_type h,
  291. const null_type& = null_type())
  292. : head (h) {}
  293. template<class T1>
  294. cons(T1& t1, const null_type&, const null_type&, const null_type&,
  295. const null_type&, const null_type&, const null_type&,
  296. const null_type&, const null_type&, const null_type&)
  297. : head (t1) {}
  298. cons(const null_type&,
  299. const null_type&, const null_type&, const null_type&,
  300. const null_type&, const null_type&, const null_type&,
  301. const null_type&, const null_type&, const null_type&)
  302. : head () {}
  303. cons( const cons& u ) : head(u.head) {}
  304. template <class HT2>
  305. cons( const cons<HT2, null_type>& u ) : head(u.head) {}
  306. template <class HT2>
  307. cons& operator=(const cons<HT2, null_type>& u )
  308. { head = u.head; return *this; }
  309. // must define assignment operator explicitely, implicit version
  310. // is illformed if HT is a reference
  311. cons& operator=(const cons& u) { head = u.head; return *this; }
  312. template <std::size_t N>
  313. typename access_traits<
  314. typename element<N, self_type>::type
  315. >::non_const_type
  316. get() {
  317. return boost::tuples::get<N>(*this);
  318. }
  319. template <std::size_t N>
  320. typename access_traits<
  321. typename element<N, self_type>::type
  322. >::const_type
  323. get() const {
  324. return boost::tuples::get<N>(*this);
  325. }
  326. };
  327. // templates for finding out the length of the tuple -------------------
  328. template<class T>
  329. struct length: boost::integral_constant<std::size_t, 1 + length<typename T::tail_type>::value>
  330. {
  331. };
  332. template<>
  333. struct length<tuple<> >: boost::integral_constant<std::size_t, 0>
  334. {
  335. };
  336. template<>
  337. struct length<tuple<> const>: boost::integral_constant<std::size_t, 0>
  338. {
  339. };
  340. template<>
  341. struct length<null_type>: boost::integral_constant<std::size_t, 0>
  342. {
  343. };
  344. template<>
  345. struct length<null_type const>: boost::integral_constant<std::size_t, 0>
  346. {
  347. };
  348. namespace detail {
  349. // Tuple to cons mapper --------------------------------------------------
  350. template <class T0, class T1, class T2, class T3, class T4,
  351. class T5, class T6, class T7, class T8, class T9>
  352. struct map_tuple_to_cons
  353. {
  354. typedef cons<T0,
  355. typename map_tuple_to_cons<T1, T2, T3, T4, T5,
  356. T6, T7, T8, T9, null_type>::type
  357. > type;
  358. };
  359. // The empty tuple is a null_type
  360. template <>
  361. struct map_tuple_to_cons<null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type>
  362. {
  363. typedef null_type type;
  364. };
  365. } // end detail
  366. // -------------------------------------------------------------------
  367. // -- tuple ------------------------------------------------------
  368. template <class T0, class T1, class T2, class T3, class T4,
  369. class T5, class T6, class T7, class T8, class T9>
  370. class tuple :
  371. public detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
  372. {
  373. public:
  374. typedef typename
  375. detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type inherited;
  376. typedef typename inherited::head_type head_type;
  377. typedef typename inherited::tail_type tail_type;
  378. // access_traits<T>::parameter_type takes non-reference types as const T&
  379. tuple() {}
  380. explicit tuple(typename access_traits<T0>::parameter_type t0)
  381. : inherited(t0, detail::cnull(), detail::cnull(), detail::cnull(),
  382. detail::cnull(), detail::cnull(), detail::cnull(),
  383. detail::cnull(), detail::cnull(), detail::cnull()) {}
  384. tuple(typename access_traits<T0>::parameter_type t0,
  385. typename access_traits<T1>::parameter_type t1)
  386. : inherited(t0, t1, detail::cnull(), detail::cnull(),
  387. detail::cnull(), detail::cnull(), detail::cnull(),
  388. detail::cnull(), detail::cnull(), detail::cnull()) {}
  389. tuple(typename access_traits<T0>::parameter_type t0,
  390. typename access_traits<T1>::parameter_type t1,
  391. typename access_traits<T2>::parameter_type t2)
  392. : inherited(t0, t1, t2, detail::cnull(), detail::cnull(),
  393. detail::cnull(), detail::cnull(), detail::cnull(),
  394. detail::cnull(), detail::cnull()) {}
  395. tuple(typename access_traits<T0>::parameter_type t0,
  396. typename access_traits<T1>::parameter_type t1,
  397. typename access_traits<T2>::parameter_type t2,
  398. typename access_traits<T3>::parameter_type t3)
  399. : inherited(t0, t1, t2, t3, detail::cnull(), detail::cnull(),
  400. detail::cnull(), detail::cnull(), detail::cnull(),
  401. detail::cnull()) {}
  402. tuple(typename access_traits<T0>::parameter_type t0,
  403. typename access_traits<T1>::parameter_type t1,
  404. typename access_traits<T2>::parameter_type t2,
  405. typename access_traits<T3>::parameter_type t3,
  406. typename access_traits<T4>::parameter_type t4)
  407. : inherited(t0, t1, t2, t3, t4, detail::cnull(), detail::cnull(),
  408. detail::cnull(), detail::cnull(), detail::cnull()) {}
  409. tuple(typename access_traits<T0>::parameter_type t0,
  410. typename access_traits<T1>::parameter_type t1,
  411. typename access_traits<T2>::parameter_type t2,
  412. typename access_traits<T3>::parameter_type t3,
  413. typename access_traits<T4>::parameter_type t4,
  414. typename access_traits<T5>::parameter_type t5)
  415. : inherited(t0, t1, t2, t3, t4, t5, detail::cnull(), detail::cnull(),
  416. detail::cnull(), detail::cnull()) {}
  417. tuple(typename access_traits<T0>::parameter_type t0,
  418. typename access_traits<T1>::parameter_type t1,
  419. typename access_traits<T2>::parameter_type t2,
  420. typename access_traits<T3>::parameter_type t3,
  421. typename access_traits<T4>::parameter_type t4,
  422. typename access_traits<T5>::parameter_type t5,
  423. typename access_traits<T6>::parameter_type t6)
  424. : inherited(t0, t1, t2, t3, t4, t5, t6, detail::cnull(),
  425. detail::cnull(), detail::cnull()) {}
  426. tuple(typename access_traits<T0>::parameter_type t0,
  427. typename access_traits<T1>::parameter_type t1,
  428. typename access_traits<T2>::parameter_type t2,
  429. typename access_traits<T3>::parameter_type t3,
  430. typename access_traits<T4>::parameter_type t4,
  431. typename access_traits<T5>::parameter_type t5,
  432. typename access_traits<T6>::parameter_type t6,
  433. typename access_traits<T7>::parameter_type t7)
  434. : inherited(t0, t1, t2, t3, t4, t5, t6, t7, detail::cnull(),
  435. detail::cnull()) {}
  436. tuple(typename access_traits<T0>::parameter_type t0,
  437. typename access_traits<T1>::parameter_type t1,
  438. typename access_traits<T2>::parameter_type t2,
  439. typename access_traits<T3>::parameter_type t3,
  440. typename access_traits<T4>::parameter_type t4,
  441. typename access_traits<T5>::parameter_type t5,
  442. typename access_traits<T6>::parameter_type t6,
  443. typename access_traits<T7>::parameter_type t7,
  444. typename access_traits<T8>::parameter_type t8)
  445. : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, detail::cnull()) {}
  446. tuple(typename access_traits<T0>::parameter_type t0,
  447. typename access_traits<T1>::parameter_type t1,
  448. typename access_traits<T2>::parameter_type t2,
  449. typename access_traits<T3>::parameter_type t3,
  450. typename access_traits<T4>::parameter_type t4,
  451. typename access_traits<T5>::parameter_type t5,
  452. typename access_traits<T6>::parameter_type t6,
  453. typename access_traits<T7>::parameter_type t7,
  454. typename access_traits<T8>::parameter_type t8,
  455. typename access_traits<T9>::parameter_type t9)
  456. : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {}
  457. template<class U1, class U2>
  458. tuple(const cons<U1, U2>& p) : inherited(p) {}
  459. template <class U1, class U2>
  460. tuple& operator=(const cons<U1, U2>& k) {
  461. inherited::operator=(k);
  462. return *this;
  463. }
  464. template <class U1, class U2>
  465. tuple& operator=(const std::pair<U1, U2>& k) {
  466. BOOST_STATIC_ASSERT(length<tuple>::value == 2);// check_length = 2
  467. this->head = k.first;
  468. this->tail.head = k.second;
  469. return *this;
  470. }
  471. };
  472. // The empty tuple
  473. template <>
  474. class tuple<null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type> :
  475. public null_type
  476. {
  477. public:
  478. typedef null_type inherited;
  479. };
  480. // Swallows any assignment (by Doug Gregor)
  481. namespace detail {
  482. struct swallow_assign;
  483. typedef void (detail::swallow_assign::*ignore_t)();
  484. struct swallow_assign {
  485. swallow_assign(ignore_t(*)(ignore_t)) {}
  486. template<typename T>
  487. swallow_assign const& operator=(const T&) const {
  488. return *this;
  489. }
  490. };
  491. } // namespace detail
  492. // "ignore" allows tuple positions to be ignored when using "tie".
  493. inline detail::ignore_t ignore(detail::ignore_t) { return 0; }
  494. // ---------------------------------------------------------------------------
  495. // The call_traits for make_tuple
  496. // Honours the reference_wrapper class.
  497. // Must be instantiated with plain or const plain types (not with references)
  498. // from template<class T> foo(const T& t) : make_tuple_traits<const T>::type
  499. // from template<class T> foo(T& t) : make_tuple_traits<T>::type
  500. // Conversions:
  501. // T -> T,
  502. // references -> compile_time_error
  503. // reference_wrapper<T> -> T&
  504. // const reference_wrapper<T> -> T&
  505. // array -> const ref array
  506. template<class T>
  507. struct make_tuple_traits {
  508. typedef T type;
  509. // commented away, see below (JJ)
  510. // typedef typename IF<
  511. // boost::is_function<T>::value,
  512. // T&,
  513. // T>::RET type;
  514. };
  515. // The is_function test was there originally for plain function types,
  516. // which can't be stored as such (we must either store them as references or
  517. // pointers). Such a type could be formed if make_tuple was called with a
  518. // reference to a function.
  519. // But this would mean that a const qualified function type was formed in
  520. // the make_tuple function and hence make_tuple can't take a function
  521. // reference as a parameter, and thus T can't be a function type.
  522. // So is_function test was removed.
  523. // (14.8.3. says that type deduction fails if a cv-qualified function type
  524. // is created. (It only applies for the case of explicitly specifying template
  525. // args, though?)) (JJ)
  526. template<class T>
  527. struct make_tuple_traits<T&> {
  528. typedef typename
  529. detail::generate_error<T&>::
  530. do_not_use_with_reference_type error;
  531. };
  532. // Arrays can't be stored as plain types; convert them to references.
  533. // All arrays are converted to const. This is because make_tuple takes its
  534. // parameters as const T& and thus the knowledge of the potential
  535. // non-constness of actual argument is lost.
  536. template<class T, std::size_t n> struct make_tuple_traits <T[n]> {
  537. typedef const T (&type)[n];
  538. };
  539. template<class T, std::size_t n>
  540. struct make_tuple_traits<const T[n]> {
  541. typedef const T (&type)[n];
  542. };
  543. template<class T, std::size_t n> struct make_tuple_traits<volatile T[n]> {
  544. typedef const volatile T (&type)[n];
  545. };
  546. template<class T, std::size_t n>
  547. struct make_tuple_traits<const volatile T[n]> {
  548. typedef const volatile T (&type)[n];
  549. };
  550. template<class T>
  551. struct make_tuple_traits<reference_wrapper<T> >{
  552. typedef T& type;
  553. };
  554. template<class T>
  555. struct make_tuple_traits<const reference_wrapper<T> >{
  556. typedef T& type;
  557. };
  558. template<>
  559. struct make_tuple_traits<detail::ignore_t(detail::ignore_t)> {
  560. typedef detail::swallow_assign type;
  561. };
  562. namespace detail {
  563. // a helper traits to make the make_tuple functions shorter (Vesa Karvonen's
  564. // suggestion)
  565. template <
  566. class T0 = null_type, class T1 = null_type, class T2 = null_type,
  567. class T3 = null_type, class T4 = null_type, class T5 = null_type,
  568. class T6 = null_type, class T7 = null_type, class T8 = null_type,
  569. class T9 = null_type
  570. >
  571. struct make_tuple_mapper {
  572. typedef
  573. tuple<typename make_tuple_traits<T0>::type,
  574. typename make_tuple_traits<T1>::type,
  575. typename make_tuple_traits<T2>::type,
  576. typename make_tuple_traits<T3>::type,
  577. typename make_tuple_traits<T4>::type,
  578. typename make_tuple_traits<T5>::type,
  579. typename make_tuple_traits<T6>::type,
  580. typename make_tuple_traits<T7>::type,
  581. typename make_tuple_traits<T8>::type,
  582. typename make_tuple_traits<T9>::type> type;
  583. };
  584. } // end detail
  585. // -make_tuple function templates -----------------------------------
  586. inline tuple<> make_tuple() {
  587. return tuple<>();
  588. }
  589. template<class T0>
  590. inline typename detail::make_tuple_mapper<T0>::type
  591. make_tuple(const T0& t0) {
  592. typedef typename detail::make_tuple_mapper<T0>::type t;
  593. return t(t0);
  594. }
  595. template<class T0, class T1>
  596. inline typename detail::make_tuple_mapper<T0, T1>::type
  597. make_tuple(const T0& t0, const T1& t1) {
  598. typedef typename detail::make_tuple_mapper<T0, T1>::type t;
  599. return t(t0, t1);
  600. }
  601. template<class T0, class T1, class T2>
  602. inline typename detail::make_tuple_mapper<T0, T1, T2>::type
  603. make_tuple(const T0& t0, const T1& t1, const T2& t2) {
  604. typedef typename detail::make_tuple_mapper<T0, T1, T2>::type t;
  605. return t(t0, t1, t2);
  606. }
  607. template<class T0, class T1, class T2, class T3>
  608. inline typename detail::make_tuple_mapper<T0, T1, T2, T3>::type
  609. make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3) {
  610. typedef typename detail::make_tuple_mapper<T0, T1, T2, T3>::type t;
  611. return t(t0, t1, t2, t3);
  612. }
  613. template<class T0, class T1, class T2, class T3, class T4>
  614. inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4>::type
  615. make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
  616. const T4& t4) {
  617. typedef typename detail::make_tuple_mapper<T0, T1, T2, T3, T4>::type t;
  618. return t(t0, t1, t2, t3, t4);
  619. }
  620. template<class T0, class T1, class T2, class T3, class T4, class T5>
  621. inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5>::type
  622. make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
  623. const T4& t4, const T5& t5) {
  624. typedef typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5>::type t;
  625. return t(t0, t1, t2, t3, t4, t5);
  626. }
  627. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6>
  628. inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5, T6>::type
  629. make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
  630. const T4& t4, const T5& t5, const T6& t6) {
  631. typedef typename detail::make_tuple_mapper
  632. <T0, T1, T2, T3, T4, T5, T6>::type t;
  633. return t(t0, t1, t2, t3, t4, t5, t6);
  634. }
  635. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
  636. class T7>
  637. inline typename detail::make_tuple_mapper<T0, T1, T2, T3, T4, T5, T6, T7>::type
  638. make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
  639. const T4& t4, const T5& t5, const T6& t6, const T7& t7) {
  640. typedef typename detail::make_tuple_mapper
  641. <T0, T1, T2, T3, T4, T5, T6, T7>::type t;
  642. return t(t0, t1, t2, t3, t4, t5, t6, t7);
  643. }
  644. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
  645. class T7, class T8>
  646. inline typename detail::make_tuple_mapper
  647. <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type
  648. make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
  649. const T4& t4, const T5& t5, const T6& t6, const T7& t7,
  650. const T8& t8) {
  651. typedef typename detail::make_tuple_mapper
  652. <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type t;
  653. return t(t0, t1, t2, t3, t4, t5, t6, t7, t8);
  654. }
  655. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
  656. class T7, class T8, class T9>
  657. inline typename detail::make_tuple_mapper
  658. <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
  659. make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
  660. const T4& t4, const T5& t5, const T6& t6, const T7& t7,
  661. const T8& t8, const T9& t9) {
  662. typedef typename detail::make_tuple_mapper
  663. <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type t;
  664. return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
  665. }
  666. namespace detail {
  667. template<class T>
  668. struct tie_traits {
  669. typedef T& type;
  670. };
  671. template<>
  672. struct tie_traits<ignore_t(ignore_t)> {
  673. typedef swallow_assign type;
  674. };
  675. template<>
  676. struct tie_traits<void> {
  677. typedef null_type type;
  678. };
  679. template <
  680. class T0 = void, class T1 = void, class T2 = void,
  681. class T3 = void, class T4 = void, class T5 = void,
  682. class T6 = void, class T7 = void, class T8 = void,
  683. class T9 = void
  684. >
  685. struct tie_mapper {
  686. typedef
  687. tuple<typename tie_traits<T0>::type,
  688. typename tie_traits<T1>::type,
  689. typename tie_traits<T2>::type,
  690. typename tie_traits<T3>::type,
  691. typename tie_traits<T4>::type,
  692. typename tie_traits<T5>::type,
  693. typename tie_traits<T6>::type,
  694. typename tie_traits<T7>::type,
  695. typename tie_traits<T8>::type,
  696. typename tie_traits<T9>::type> type;
  697. };
  698. }
  699. // Tie function templates -------------------------------------------------
  700. template<class T0>
  701. inline typename detail::tie_mapper<T0>::type
  702. tie(T0& t0) {
  703. typedef typename detail::tie_mapper<T0>::type t;
  704. return t(t0);
  705. }
  706. template<class T0, class T1>
  707. inline typename detail::tie_mapper<T0, T1>::type
  708. tie(T0& t0, T1& t1) {
  709. typedef typename detail::tie_mapper<T0, T1>::type t;
  710. return t(t0, t1);
  711. }
  712. template<class T0, class T1, class T2>
  713. inline typename detail::tie_mapper<T0, T1, T2>::type
  714. tie(T0& t0, T1& t1, T2& t2) {
  715. typedef typename detail::tie_mapper<T0, T1, T2>::type t;
  716. return t(t0, t1, t2);
  717. }
  718. template<class T0, class T1, class T2, class T3>
  719. inline typename detail::tie_mapper<T0, T1, T2, T3>::type
  720. tie(T0& t0, T1& t1, T2& t2, T3& t3) {
  721. typedef typename detail::tie_mapper<T0, T1, T2, T3>::type t;
  722. return t(t0, t1, t2, t3);
  723. }
  724. template<class T0, class T1, class T2, class T3, class T4>
  725. inline typename detail::tie_mapper<T0, T1, T2, T3, T4>::type
  726. tie(T0& t0, T1& t1, T2& t2, T3& t3,
  727. T4& t4) {
  728. typedef typename detail::tie_mapper<T0, T1, T2, T3, T4>::type t;
  729. return t(t0, t1, t2, t3, t4);
  730. }
  731. template<class T0, class T1, class T2, class T3, class T4, class T5>
  732. inline typename detail::tie_mapper<T0, T1, T2, T3, T4, T5>::type
  733. tie(T0& t0, T1& t1, T2& t2, T3& t3,
  734. T4& t4, T5& t5) {
  735. typedef typename detail::tie_mapper<T0, T1, T2, T3, T4, T5>::type t;
  736. return t(t0, t1, t2, t3, t4, t5);
  737. }
  738. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6>
  739. inline typename detail::tie_mapper<T0, T1, T2, T3, T4, T5, T6>::type
  740. tie(T0& t0, T1& t1, T2& t2, T3& t3,
  741. T4& t4, T5& t5, T6& t6) {
  742. typedef typename detail::tie_mapper
  743. <T0, T1, T2, T3, T4, T5, T6>::type t;
  744. return t(t0, t1, t2, t3, t4, t5, t6);
  745. }
  746. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
  747. class T7>
  748. inline typename detail::tie_mapper<T0, T1, T2, T3, T4, T5, T6, T7>::type
  749. tie(T0& t0, T1& t1, T2& t2, T3& t3,
  750. T4& t4, T5& t5, T6& t6, T7& t7) {
  751. typedef typename detail::tie_mapper
  752. <T0, T1, T2, T3, T4, T5, T6, T7>::type t;
  753. return t(t0, t1, t2, t3, t4, t5, t6, t7);
  754. }
  755. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
  756. class T7, class T8>
  757. inline typename detail::tie_mapper
  758. <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type
  759. tie(T0& t0, T1& t1, T2& t2, T3& t3,
  760. T4& t4, T5& t5, T6& t6, T7& t7,
  761. T8& t8) {
  762. typedef typename detail::tie_mapper
  763. <T0, T1, T2, T3, T4, T5, T6, T7, T8>::type t;
  764. return t(t0, t1, t2, t3, t4, t5, t6, t7, t8);
  765. }
  766. template<class T0, class T1, class T2, class T3, class T4, class T5, class T6,
  767. class T7, class T8, class T9>
  768. inline typename detail::tie_mapper
  769. <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
  770. tie(T0& t0, T1& t1, T2& t2, T3& t3,
  771. T4& t4, T5& t5, T6& t6, T7& t7,
  772. T8& t8, T9& t9) {
  773. typedef typename detail::tie_mapper
  774. <T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type t;
  775. return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
  776. }
  777. template <class T0, class T1, class T2, class T3, class T4,
  778. class T5, class T6, class T7, class T8, class T9>
  779. void swap(tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& lhs,
  780. tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& rhs);
  781. inline void swap(null_type&, null_type&) {}
  782. template<class HH>
  783. inline void swap(cons<HH, null_type>& lhs, cons<HH, null_type>& rhs) {
  784. ::boost::core::invoke_swap(lhs.head, rhs.head);
  785. }
  786. template<class HH, class TT>
  787. inline void swap(cons<HH, TT>& lhs, cons<HH, TT>& rhs) {
  788. ::boost::core::invoke_swap(lhs.head, rhs.head);
  789. ::boost::tuples::swap(lhs.tail, rhs.tail);
  790. }
  791. template <class T0, class T1, class T2, class T3, class T4,
  792. class T5, class T6, class T7, class T8, class T9>
  793. inline void swap(tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& lhs,
  794. tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& rhs) {
  795. typedef tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> tuple_type;
  796. typedef typename tuple_type::inherited base;
  797. ::boost::tuples::swap(static_cast<base&>(lhs), static_cast<base&>(rhs));
  798. }
  799. } // end of namespace tuples
  800. } // end of namespace boost
  801. #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  802. #pragma GCC diagnostic pop
  803. #endif
  804. #endif // BOOST_TUPLE_BASIC_HPP