tuple.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2011-2012 Steven Watanabe
  4. //
  5. // Distributed under the Boost Software License Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // $Id$
  10. #if !defined(BOOST_PP_IS_ITERATING)
  11. #ifndef BOOST_TYPE_ERASURE_TUPLE_HPP_INCLUDED
  12. #define BOOST_TYPE_ERASURE_TUPLE_HPP_INCLUDED
  13. #include <boost/config.hpp>
  14. #ifdef BOOST_TYPE_ERASURE_DOXYGEN
  15. namespace boost {
  16. namespace type_erasure {
  17. /**
  18. * @ref tuple is a Boost.Fusion Random Access Sequence containing
  19. * @ref any "anys". @c Concept specifies the \Concept for each
  20. * of the elements. The remaining arguments must be (possibly const
  21. * and/or reference qualified) placeholders, which are the
  22. * @ref placeholder "placeholders" of the elements.
  23. */
  24. template<class Concept, class... T>
  25. class tuple
  26. {
  27. public:
  28. /**
  29. * Constructs a tuple. Each element of @c args will
  30. * be used to initialize the corresponding @ref any member.
  31. * The @ref binding for the tuple elements is determined
  32. * by mapping the placeholders in @c T to the corresponding
  33. * types in @c U.
  34. */
  35. template<class... U>
  36. explicit tuple(U&&... args);
  37. };
  38. /**
  39. * Returns the Nth @ref any in the tuple.
  40. */
  41. template<int N, class Concept, class... T>
  42. any<Concept, TN>& get(tuple<Concept, T...>& arg);
  43. /** \overload */
  44. template<int N, class Concept, class... T>
  45. const any<Concept, TN>& get(const tuple<Concept, T...>& arg);
  46. }
  47. }
  48. #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  49. #include <boost/mpl/int.hpp>
  50. #include <boost/mpl/bool.hpp>
  51. #include <boost/mpl/map.hpp>
  52. #include <boost/mpl/insert.hpp>
  53. #include <boost/type_traits/remove_reference.hpp>
  54. #include <boost/type_traits/remove_const.hpp>
  55. #include <boost/fusion/include/category_of.hpp>
  56. #include <boost/fusion/include/iterator_facade.hpp>
  57. #include <boost/fusion/include/sequence_facade.hpp>
  58. #include <boost/type_erasure/any.hpp>
  59. #include <boost/type_erasure/static_binding.hpp>
  60. #include <boost/type_erasure/config.hpp>
  61. namespace boost {
  62. namespace type_erasure {
  63. template<class Concept, class... T>
  64. struct cons;
  65. template<class Concept>
  66. struct cons<Concept>
  67. {
  68. template<class Binding>
  69. cons(const Binding&) {}
  70. };
  71. template<class Concept, class T0, class... T>
  72. struct cons<Concept, T0, T...>
  73. {
  74. typedef any<Concept, T0> value_type;
  75. typedef cons<Concept, T...> rest_type;
  76. template<class Binding, class U0, class... U>
  77. cons(const Binding& b, U0&& u0, U&&... u)
  78. : value(std::forward<U0>(u0), b),
  79. rest(b, std::forward<U>(u)...)
  80. {}
  81. any<Concept, T0> value;
  82. cons<Concept, T...> rest;
  83. };
  84. namespace detail {
  85. template<int N, class Cons>
  86. struct cons_advance
  87. {
  88. typedef typename cons_advance<N-1, Cons>::type::rest_type type;
  89. static const type& call(const Cons& c)
  90. {
  91. return cons_advance<N-1, Cons>::call(c).rest;
  92. }
  93. };
  94. template<class Cons>
  95. struct cons_advance<0, Cons>
  96. {
  97. typedef Cons type;
  98. static const type& call(const Cons& c)
  99. {
  100. return c;
  101. }
  102. };
  103. template<class... T>
  104. struct make_map;
  105. template<class T0, class... T>
  106. struct make_map<T0, T...>
  107. {
  108. typedef typename ::boost::mpl::insert<
  109. typename ::boost::type_erasure::detail::make_map<T...>::type,
  110. T0
  111. >::type type;
  112. };
  113. template<>
  114. struct make_map<>
  115. {
  116. typedef ::boost::mpl::map0<> type;
  117. };
  118. }
  119. /** INTERNAL ONLY */
  120. template<class Tuple, int N>
  121. class tuple_iterator :
  122. public ::boost::fusion::iterator_facade<
  123. tuple_iterator<Tuple, N>,
  124. ::boost::fusion::random_access_traversal_tag
  125. >
  126. {
  127. public:
  128. typedef ::boost::mpl::int_<N> index;
  129. explicit tuple_iterator(Tuple& t_arg) : t(&t_arg) {}
  130. template<class It>
  131. struct value_of
  132. {
  133. typedef typename Tuple::template value_at<Tuple, mpl::int_<N> >::type type;
  134. };
  135. template<class It>
  136. struct deref
  137. {
  138. typedef typename Tuple::template at<Tuple, mpl::int_<N> >::type type;
  139. static type call(It it)
  140. {
  141. return Tuple::template at<Tuple, mpl::int_<N> >::call(*it.t);
  142. }
  143. };
  144. template<class It, class M>
  145. struct advance
  146. {
  147. typedef tuple_iterator<Tuple, (It::index::value+M::value)> type;
  148. static type call(It it) { return type(*it.t); }
  149. };
  150. template<class It>
  151. struct next : advance<It, ::boost::mpl::int_<1> > {};
  152. template<class It>
  153. struct prior : advance<It, ::boost::mpl::int_<-1> > {};
  154. template<class It1, class It2>
  155. struct distance
  156. {
  157. typedef typename ::boost::mpl::minus<
  158. typename It2::index,
  159. typename It1::index
  160. >::type type;
  161. static type call(It1, It2) { return type(); }
  162. };
  163. private:
  164. Tuple* t;
  165. };
  166. template<class Concept, class... T>
  167. class tuple :
  168. public ::boost::fusion::sequence_facade<
  169. ::boost::type_erasure::tuple<Concept, T...>,
  170. ::boost::fusion::forward_traversal_tag
  171. >
  172. {
  173. public:
  174. template<class... U>
  175. explicit tuple(U&&... args)
  176. : impl(
  177. ::boost::type_erasure::make_binding<
  178. typename ::boost::type_erasure::detail::make_map<
  179. ::boost::mpl::pair<
  180. typename ::boost::remove_const<
  181. typename ::boost::remove_reference<T>::type
  182. >::type,
  183. typename ::boost::remove_const<
  184. typename ::boost::remove_reference<U>::type
  185. >::type
  186. >...
  187. >::type
  188. >(),
  189. std::forward<U>(args)...)
  190. {}
  191. template<class Seq>
  192. struct begin
  193. {
  194. typedef ::boost::type_erasure::tuple_iterator<
  195. Seq,
  196. 0
  197. > type;
  198. static type call(Seq& seq) { return type(seq); }
  199. };
  200. template<class Seq>
  201. struct end
  202. {
  203. typedef ::boost::type_erasure::tuple_iterator<
  204. Seq,
  205. sizeof...(T)
  206. > type;
  207. static type call(Seq& seq) { return type(seq); }
  208. };
  209. template<class Seq>
  210. struct size
  211. {
  212. typedef ::boost::mpl::int_<sizeof...(T)> type;
  213. static type call(Seq& seq) { return type(); }
  214. };
  215. template<class Seq>
  216. struct empty
  217. {
  218. typedef ::boost::mpl::bool_<sizeof...(T) == 0> type;
  219. static type call(Seq& seq) { return type(); }
  220. };
  221. template<class Seq, class N>
  222. struct at
  223. {
  224. typedef typename ::boost::type_erasure::detail::cons_advance<
  225. N::value,
  226. ::boost::type_erasure::cons<Concept, T...>
  227. >::type::value_type value_type;
  228. typedef typename ::boost::mpl::if_< ::boost::is_const<Seq>,
  229. const value_type&,
  230. value_type&
  231. >::type type;
  232. static type call(Seq& seq)
  233. {
  234. return const_cast<type>(
  235. ::boost::type_erasure::detail::cons_advance<
  236. N::value,
  237. ::boost::type_erasure::cons<Concept, T...>
  238. >::call(seq.impl).value
  239. );
  240. }
  241. };
  242. template<class Seq, class N>
  243. struct value_at
  244. {
  245. typedef typename ::boost::type_erasure::detail::cons_advance<
  246. N::value,
  247. ::boost::type_erasure::cons<Concept, T...>
  248. >::type::value_type value_type;
  249. };
  250. ::boost::type_erasure::cons<Concept, T...> impl;
  251. };
  252. template<int N, class Concept, class... T>
  253. typename ::boost::type_erasure::detail::cons_advance<
  254. N,
  255. ::boost::type_erasure::cons<Concept, T...>
  256. >::type::value_type& get(::boost::type_erasure::tuple<Concept, T...>& t)
  257. {
  258. return const_cast<
  259. typename ::boost::type_erasure::detail::cons_advance<
  260. N,
  261. ::boost::type_erasure::cons<Concept, T...>
  262. >::type::value_type&
  263. >(
  264. ::boost::type_erasure::detail::cons_advance<N,
  265. ::boost::type_erasure::cons<Concept, T...>
  266. >::call(t.impl).value
  267. );
  268. }
  269. template<int N, class Concept, class... T>
  270. const typename ::boost::type_erasure::detail::cons_advance<
  271. N,
  272. ::boost::type_erasure::cons<Concept, T...>
  273. >::type::value_type& get(const ::boost::type_erasure::tuple<Concept, T...>& t)
  274. {
  275. return ::boost::type_erasure::detail::cons_advance<
  276. N,
  277. ::boost::type_erasure::cons<Concept, T...>
  278. >::call(t.impl).value;
  279. }
  280. }
  281. }
  282. #else
  283. #include <boost/mpl/int.hpp>
  284. #include <boost/mpl/minus.hpp>
  285. #include <boost/mpl/equal_to.hpp>
  286. #include <boost/mpl/map.hpp>
  287. #include <boost/fusion/include/category_of.hpp>
  288. #include <boost/fusion/include/iterator_facade.hpp>
  289. #include <boost/fusion/include/sequence_facade.hpp>
  290. #include <boost/preprocessor/cat.hpp>
  291. #include <boost/preprocessor/iteration/iterate.hpp>
  292. #include <boost/preprocessor/repetition/repeat.hpp>
  293. #include <boost/preprocessor/repetition/enum.hpp>
  294. #include <boost/preprocessor/repetition/enum_params.hpp>
  295. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  296. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  297. #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  298. #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
  299. #include <boost/type_erasure/any.hpp>
  300. #include <boost/type_erasure/static_binding.hpp>
  301. #include <boost/type_erasure/config.hpp>
  302. namespace boost {
  303. namespace type_erasure {
  304. /** INTERNAL ONLY */
  305. struct na {};
  306. namespace detail {
  307. template<int N, class Tuple>
  308. struct get_impl;
  309. template<class Concept,
  310. BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
  311. BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T, ::boost::type_erasure::na)>
  312. struct tuple_storage;
  313. }
  314. /** INTERNAL ONLY */
  315. template<class Tuple, int N>
  316. class tuple_iterator :
  317. public ::boost::fusion::iterator_facade<
  318. tuple_iterator<Tuple, N>,
  319. ::boost::fusion::random_access_traversal_tag
  320. >
  321. {
  322. public:
  323. typedef ::boost::mpl::int_<N> index;
  324. explicit tuple_iterator(Tuple& t_arg) : t(&t_arg) {}
  325. template<class It>
  326. struct value_of
  327. {
  328. typedef typename ::boost::type_erasure::detail::get_impl<
  329. It::index::value,
  330. Tuple
  331. >::value_type type;
  332. };
  333. template<class It>
  334. struct deref :
  335. ::boost::type_erasure::detail::get_impl<It::index::value, Tuple>
  336. {
  337. typedef typename ::boost::type_erasure::detail::get_impl<
  338. It::index::value,
  339. Tuple
  340. >::type type;
  341. static type call(It it)
  342. {
  343. return ::boost::type_erasure::detail::get_impl<
  344. It::index::value,
  345. Tuple
  346. >::call(*it.t);
  347. }
  348. };
  349. template<class It, class M>
  350. struct advance
  351. {
  352. typedef tuple_iterator<Tuple, (It::index::value+M::value)> type;
  353. static type call(It it) { return type(*it.t); }
  354. };
  355. template<class It>
  356. struct next : advance<It, ::boost::mpl::int_<1> > {};
  357. template<class It>
  358. struct prior : advance<It, ::boost::mpl::int_<-1> > {};
  359. template<class It1, class It2>
  360. struct distance
  361. {
  362. typedef typename ::boost::mpl::minus<
  363. typename It2::index,
  364. typename It1::index
  365. >::type type;
  366. static type call(It1, It2) { return type(); }
  367. };
  368. private:
  369. Tuple* t;
  370. };
  371. /** INTERNAL ONLY */
  372. template<class Derived>
  373. struct tuple_base :
  374. ::boost::fusion::sequence_facade<
  375. Derived,
  376. ::boost::fusion::random_access_traversal_tag
  377. >
  378. {
  379. template<class Seq>
  380. struct begin
  381. {
  382. typedef ::boost::type_erasure::tuple_iterator<Seq, 0> type;
  383. static type call(Seq& seq) { return type(seq); }
  384. };
  385. template<class Seq>
  386. struct end
  387. {
  388. typedef ::boost::type_erasure::tuple_iterator<
  389. Seq,
  390. Seq::tuple_size::value
  391. > type;
  392. static type call(Seq& seq) { return type(seq); }
  393. };
  394. template<class Seq>
  395. struct size
  396. {
  397. typedef typename Seq::tuple_size type;
  398. static type call(Seq& seq) { return type(); }
  399. };
  400. template<class Seq>
  401. struct empty
  402. {
  403. typedef typename boost::mpl::equal_to<
  404. typename Seq::tuple_size,
  405. boost::mpl::int_<0>
  406. >::type type;
  407. static type call(Seq& seq) { return type(); }
  408. };
  409. template<class Seq, class N>
  410. struct at : ::boost::type_erasure::detail::get_impl<N::value, Seq> {};
  411. template<class Seq, class N>
  412. struct value_at
  413. {
  414. typedef typename ::boost::type_erasure::detail::get_impl<
  415. N::value,
  416. Seq
  417. >::value_type type;
  418. };
  419. };
  420. template<class Concept,
  421. BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
  422. BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T, ::boost::type_erasure::na)>
  423. class tuple;
  424. template<
  425. int N,
  426. class Concept
  427. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T)
  428. >
  429. typename detail::get_impl<
  430. N,
  431. tuple<
  432. Concept
  433. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
  434. >
  435. >::type get(
  436. tuple<
  437. Concept
  438. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
  439. >& arg)
  440. {
  441. return detail::get_impl<
  442. N,
  443. tuple<
  444. Concept
  445. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
  446. >
  447. >::call(arg);
  448. }
  449. template<
  450. int N,
  451. class Concept
  452. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T)
  453. >
  454. typename detail::get_impl<
  455. N,
  456. const tuple<
  457. Concept
  458. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
  459. >
  460. >::type get(
  461. const tuple<
  462. Concept
  463. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
  464. >& arg)
  465. {
  466. return detail::get_impl<
  467. N,
  468. const tuple<
  469. Concept
  470. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
  471. >
  472. >::call(arg);
  473. }
  474. /** INTERNAL ONLY */
  475. #define BOOST_PP_FILENAME_1 <boost/type_erasure/tuple.hpp>
  476. /** INTERNAL ONLY */
  477. #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE)
  478. #include BOOST_PP_ITERATE()
  479. }
  480. }
  481. #endif
  482. #endif
  483. #else
  484. #define N BOOST_PP_ITERATION()
  485. #define BOOST_TYPE_ERASURE_TAG_TYPEDEF(z, n, data) \
  486. typedef BOOST_PP_CAT(T, n) BOOST_PP_CAT(tag_type, n); \
  487. typedef typename ::boost::remove_reference<BOOST_PP_CAT(T, n)>::type \
  488. BOOST_PP_CAT(tag, n);
  489. #define BOOST_TYPE_ERASURE_PAIR(z, n, data) \
  490. ::boost::mpl::pair<BOOST_PP_CAT(tag, n), BOOST_PP_CAT(U, n)>
  491. #define BOOST_TYPE_ERASURE_CONSTRUCT(z, n, data)\
  492. BOOST_PP_CAT(t, n)(BOOST_PP_CAT(u, n), table)
  493. #define BOOST_TYPE_ERASURE_TUPLE_MEMBER(z, n, data)\
  494. ::boost::type_erasure::any<Concept, BOOST_PP_CAT(T, n)> BOOST_PP_CAT(t, n);
  495. #if N == 1
  496. #define BOOST_TYPE_ERASURE_EXPLICIT explicit
  497. #else
  498. #define BOOST_TYPE_ERASURE_EXPLICIT
  499. #endif
  500. namespace detail {
  501. template<class Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)>
  502. struct tuple_storage
  503. #if N != BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE
  504. <Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, T)>
  505. #endif
  506. {
  507. #if N
  508. template<class Table BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)>
  509. tuple_storage(
  510. const Table& table BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, &u))
  511. :
  512. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_CONSTRUCT, ~) {}
  513. #else
  514. template<class Table>
  515. explicit tuple_storage(const Table&) {}
  516. #endif
  517. BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_TUPLE_MEMBER, `)
  518. };
  519. #if N != BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE
  520. template<class Tuple>
  521. struct get_impl<N, Tuple>
  522. {
  523. typedef any<
  524. typename Tuple::concept_type,
  525. typename Tuple::BOOST_PP_CAT(tag_type, N)
  526. > value_type;
  527. typedef value_type& type;
  528. static type call(Tuple& arg)
  529. { return arg.impl.BOOST_PP_CAT(t, N); }
  530. };
  531. template<class Tuple>
  532. struct get_impl<N, const Tuple>
  533. {
  534. typedef any<
  535. typename Tuple::concept_type,
  536. typename Tuple::BOOST_PP_CAT(tag_type, N)
  537. > value_type;
  538. typedef const value_type& type;
  539. static type call(const Tuple& arg)
  540. { return arg.impl.BOOST_PP_CAT(t, N); }
  541. };
  542. #endif
  543. }
  544. template<class Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)>
  545. class tuple
  546. #if N != BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE
  547. <Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, T)>
  548. #endif
  549. : public tuple_base<tuple<Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, T)> >
  550. {
  551. typedef Concept concept_type;
  552. BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_TAG_TYPEDEF, ~)
  553. public:
  554. typedef ::boost::mpl::int_<N> tuple_size;
  555. #if N
  556. template<BOOST_PP_ENUM_PARAMS(N, class U)>
  557. #endif
  558. BOOST_TYPE_ERASURE_EXPLICIT
  559. tuple(BOOST_PP_ENUM_BINARY_PARAMS(N, U, &u)) :
  560. impl(
  561. ::boost::type_erasure::make_binding<
  562. ::boost::mpl::map<
  563. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_PAIR, ~)
  564. >
  565. >()
  566. BOOST_PP_ENUM_TRAILING_PARAMS(N, u)
  567. )
  568. {}
  569. #if N
  570. template<BOOST_PP_ENUM_PARAMS(N, class U)>
  571. BOOST_TYPE_ERASURE_EXPLICIT
  572. tuple(BOOST_PP_ENUM_BINARY_PARAMS(N, const U, &u)) :
  573. impl(
  574. ::boost::type_erasure::make_binding<
  575. ::boost::mpl::map<
  576. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_PAIR, ~)
  577. >
  578. >()
  579. BOOST_PP_ENUM_TRAILING_PARAMS(N, u)
  580. )
  581. {}
  582. #endif
  583. private:
  584. template<int M, class Tuple>
  585. friend struct ::boost::type_erasure::detail::get_impl;
  586. ::boost::type_erasure::detail::tuple_storage<
  587. Concept
  588. BOOST_PP_ENUM_TRAILING_PARAMS(N, T)
  589. > impl;
  590. };
  591. #undef BOOST_TYPE_ERASURE_EXPLICIT
  592. #undef BOOST_TYPE_ERASURE_TUPLE_MEMBER
  593. #undef BOOST_TYPE_ERASURE_CONSTRUCT
  594. #undef BOOST_TYPE_ERASURE_PAIR
  595. #undef BOOST_TYPE_ERASURE_TAG_TYPEDEF
  596. #undef N
  597. #endif