initializer.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. //-----------------------------------------------------------------------------
  2. // boost variant/detail/initializer.hpp header file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2002-2003
  7. // Eric Friedman, Itay Maman
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See
  10. // accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP
  13. #define BOOST_VARIANT_DETAIL_INITIALIZER_HPP
  14. #include <new> // for placement new
  15. #include <boost/config.hpp>
  16. #include <boost/call_traits.hpp>
  17. #include <boost/detail/reference_content.hpp>
  18. #include <boost/variant/recursive_wrapper_fwd.hpp>
  19. #include <boost/variant/detail/move.hpp>
  20. #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
  21. # include <boost/mpl/aux_/value_wknd.hpp>
  22. # include <boost/mpl/int.hpp>
  23. # include <boost/mpl/iter_fold.hpp>
  24. # include <boost/mpl/next.hpp>
  25. # include <boost/mpl/deref.hpp>
  26. # include <boost/mpl/pair.hpp>
  27. # include <boost/mpl/protect.hpp>
  28. #else
  29. # include <boost/variant/variant_fwd.hpp>
  30. # include <boost/preprocessor/cat.hpp>
  31. # include <boost/preprocessor/enum.hpp>
  32. # include <boost/preprocessor/repeat.hpp>
  33. #endif
  34. namespace boost {
  35. namespace detail { namespace variant {
  36. ///////////////////////////////////////////////////////////////////////////////
  37. // (detail) support to simulate standard overload resolution rules
  38. //
  39. // The below initializers allows variant to follow standard overload
  40. // resolution rules over the specified set of bounded types.
  41. //
  42. // On compilers where using declarations in class templates can correctly
  43. // avoid name hiding, use an optimal solution based on the variant's typelist.
  44. //
  45. // Otherwise, use a preprocessor workaround based on knowledge of the fixed
  46. // size of the variant's psuedo-variadic template parameter list.
  47. //
  48. #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
  49. // (detail) quoted metafunction make_initializer_node
  50. //
  51. // Exposes a pair whose first type is a node in the initializer hierarchy.
  52. //
  53. struct make_initializer_node
  54. {
  55. template <typename BaseIndexPair, typename Iterator>
  56. struct apply
  57. {
  58. private: // helpers, for metafunction result (below)
  59. typedef typename BaseIndexPair::first
  60. base;
  61. typedef typename BaseIndexPair::second
  62. index;
  63. class initializer_node
  64. : public base
  65. {
  66. private: // helpers, for static functions (below)
  67. typedef typename mpl::deref<Iterator>::type
  68. recursive_enabled_T;
  69. typedef typename unwrap_recursive<recursive_enabled_T>::type
  70. public_T;
  71. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  72. typedef boost::is_reference<public_T>
  73. is_reference_content_t;
  74. typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type
  75. param_T;
  76. template <class T> struct disable_overload{};
  77. typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type
  78. param2_T;
  79. #else
  80. typedef typename call_traits<public_T>::param_type
  81. param_T;
  82. #endif
  83. public: // static functions
  84. using base::initialize;
  85. static int initialize(void* dest, param_T operand)
  86. {
  87. typedef typename boost::detail::make_reference_content<
  88. recursive_enabled_T
  89. >::type internal_T;
  90. new(dest) internal_T(operand);
  91. return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
  92. }
  93. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  94. static int initialize(void* dest, param2_T operand)
  95. {
  96. // This assert must newer trigger, because all the reference contents are
  97. // handled by the initilize(void* dest, param_T operand) function above
  98. BOOST_ASSERT(!is_reference_content_t::value);
  99. typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T;
  100. new(dest) value_T( boost::detail::variant::move(operand) );
  101. return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
  102. }
  103. #endif
  104. };
  105. friend class initializer_node;
  106. public: // metafunction result
  107. typedef mpl::pair<
  108. initializer_node
  109. , typename mpl::next< index >::type
  110. > type;
  111. };
  112. };
  113. // (detail) class initializer_root
  114. //
  115. // Every level of the initializer hierarchy must expose the name
  116. // "initialize," so initializer_root provides a dummy function:
  117. //
  118. class initializer_root
  119. {
  120. public: // static functions
  121. static void initialize();
  122. };
  123. #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
  124. // Obsolete. Remove.
  125. #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \
  126. BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \
  127. /**/
  128. // Obsolete. Remove.
  129. #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
  130. typedef typename unwrap_recursive< \
  131. BOOST_PP_CAT(recursive_enabled_T,N) \
  132. >::type BOOST_PP_CAT(public_T,N); \
  133. typedef typename call_traits< \
  134. BOOST_PP_CAT(public_T,N) \
  135. >::param_type BOOST_PP_CAT(param_T,N); \
  136. /**/
  137. template < BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) >
  138. struct preprocessor_list_initializer
  139. {
  140. public: // static functions
  141. #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \
  142. typedef typename unwrap_recursive< \
  143. BOOST_PP_CAT(recursive_enabled_T,N) \
  144. >::type BOOST_PP_CAT(public_T,N); \
  145. typedef typename call_traits< \
  146. BOOST_PP_CAT(public_T,N) \
  147. >::param_type BOOST_PP_CAT(param_T,N); \
  148. static int initialize( \
  149. void* dest \
  150. , BOOST_PP_CAT(param_T,N) operand \
  151. ) \
  152. { \
  153. typedef typename boost::detail::make_reference_content< \
  154. BOOST_PP_CAT(recursive_enabled_T,N) \
  155. >::type internal_T; \
  156. \
  157. new(dest) internal_T(operand); \
  158. return (N); /*which*/ \
  159. } \
  160. /**/
  161. BOOST_PP_REPEAT(
  162. BOOST_VARIANT_LIMIT_TYPES
  163. , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
  164. , _
  165. )
  166. #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
  167. };
  168. #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
  169. }} // namespace detail::variant
  170. } // namespace boost
  171. ///////////////////////////////////////////////////////////////////////////////
  172. // macro BOOST_VARIANT_AUX_INITIALIZER_T
  173. //
  174. // Given both the variant's typelist and a basename for forming the list of
  175. // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer
  176. // most appropriate to the current compiler.
  177. //
  178. #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
  179. #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
  180. ::boost::mpl::iter_fold< \
  181. mpl_seq \
  182. , ::boost::mpl::pair< \
  183. ::boost::detail::variant::initializer_root \
  184. , ::boost::mpl::int_<0> \
  185. > \
  186. , ::boost::mpl::protect< \
  187. ::boost::detail::variant::make_initializer_node \
  188. > \
  189. >::type::first \
  190. /**/
  191. #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
  192. // Obsolete. Remove.
  193. #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
  194. BOOST_VARIANT_ENUM_PARAMS(typename_base) \
  195. /**/
  196. #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
  197. ::boost::detail::variant::preprocessor_list_initializer< \
  198. BOOST_VARIANT_ENUM_PARAMS(typename_base) \
  199. > \
  200. /**/
  201. #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
  202. #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP