initializer.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  125. #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \
  126. BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \
  127. /**/
  128. #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
  129. typedef typename unwrap_recursive< \
  130. BOOST_PP_CAT(recursive_enabled_T,N) \
  131. >::type BOOST_PP_CAT(public_T,N); \
  132. typedef typename call_traits< \
  133. BOOST_PP_CAT(public_T,N) \
  134. >::param_type BOOST_PP_CAT(param_T,N); \
  135. /**/
  136. # else // MSVC7 and below
  137. #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \
  138. BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \
  139. , BOOST_VARIANT_ENUM_PARAMS(typename param_T) \
  140. /**/
  141. #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
  142. /**/
  143. # endif // MSVC7 and below workaround
  144. template < BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS >
  145. struct preprocessor_list_initializer
  146. {
  147. public: // static functions
  148. #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \
  149. BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
  150. static int initialize( \
  151. void* dest \
  152. , BOOST_PP_CAT(param_T,N) operand \
  153. ) \
  154. { \
  155. typedef typename boost::detail::make_reference_content< \
  156. BOOST_PP_CAT(recursive_enabled_T,N) \
  157. >::type internal_T; \
  158. \
  159. new(dest) internal_T(operand); \
  160. return (N); /*which*/ \
  161. } \
  162. /**/
  163. BOOST_PP_REPEAT(
  164. BOOST_VARIANT_LIMIT_TYPES
  165. , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
  166. , _
  167. )
  168. #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
  169. };
  170. # if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
  171. #if !defined(BOOST_VARIANT_AUX_ECHO)
  172. # define BOOST_VARIANT_AUX_ECHO(z,N,token) token
  173. #endif
  174. template <>
  175. struct preprocessor_list_initializer<
  176. BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, int)
  177. , BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, const int)
  178. >
  179. {
  180. };
  181. # endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
  182. #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
  183. }} // namespace detail::variant
  184. } // namespace boost
  185. ///////////////////////////////////////////////////////////////////////////////
  186. // macro BOOST_VARIANT_AUX_INITIALIZER_T
  187. //
  188. // Given both the variant's typelist and a basename for forming the list of
  189. // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer
  190. // most appropriate to the current compiler.
  191. //
  192. #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
  193. #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
  194. ::boost::mpl::iter_fold< \
  195. mpl_seq \
  196. , ::boost::mpl::pair< \
  197. ::boost::detail::variant::initializer_root \
  198. , ::boost::mpl::int_<0> \
  199. > \
  200. , ::boost::mpl::protect< \
  201. ::boost::detail::variant::make_initializer_node \
  202. > \
  203. >::type::first \
  204. /**/
  205. #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
  206. # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  207. #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
  208. BOOST_VARIANT_ENUM_PARAMS(typename_base) \
  209. /**/
  210. # else // MSVC7 and below
  211. #define BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE(z,N,T) \
  212. ::boost::call_traits< \
  213. ::boost::unwrap_recursive<BOOST_PP_CAT(T,N)>::type \
  214. >::param_type \
  215. /**/
  216. #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
  217. BOOST_VARIANT_ENUM_PARAMS(typename_base) \
  218. , BOOST_PP_ENUM( \
  219. BOOST_VARIANT_LIMIT_TYPES \
  220. , BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE \
  221. , typename_base \
  222. ) \
  223. /**/
  224. # endif // MSVC7 workaround
  225. #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
  226. ::boost::detail::variant::preprocessor_list_initializer< \
  227. BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
  228. > \
  229. /**/
  230. #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
  231. #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP