tuple_basic.hpp 32 KB

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