initializer.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. # include <boost/mpl/aux_/value_wknd.hpp>
  21. # include <boost/mpl/int.hpp>
  22. # include <boost/mpl/iter_fold.hpp>
  23. # include <boost/mpl/next.hpp>
  24. # include <boost/mpl/deref.hpp>
  25. # include <boost/mpl/pair.hpp>
  26. # include <boost/mpl/protect.hpp>
  27. namespace boost {
  28. namespace detail { namespace variant {
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // (detail) support to simulate standard overload resolution rules
  31. //
  32. // The below initializers allows variant to follow standard overload
  33. // resolution rules over the specified set of bounded types.
  34. //
  35. // On compilers where using declarations in class templates can correctly
  36. // avoid name hiding, use an optimal solution based on the variant's typelist.
  37. //
  38. // Otherwise, use a preprocessor workaround based on knowledge of the fixed
  39. // size of the variant's psuedo-variadic template parameter list.
  40. //
  41. // (detail) quoted metafunction make_initializer_node
  42. //
  43. // Exposes a pair whose first type is a node in the initializer hierarchy.
  44. //
  45. struct make_initializer_node
  46. {
  47. template <typename BaseIndexPair, typename Iterator>
  48. struct apply
  49. {
  50. private: // helpers, for metafunction result (below)
  51. typedef typename BaseIndexPair::first
  52. base;
  53. typedef typename BaseIndexPair::second
  54. index;
  55. class initializer_node
  56. : public base
  57. {
  58. private: // helpers, for static functions (below)
  59. typedef typename mpl::deref<Iterator>::type
  60. recursive_enabled_T;
  61. typedef typename unwrap_recursive<recursive_enabled_T>::type
  62. public_T;
  63. typedef boost::is_reference<public_T>
  64. is_reference_content_t;
  65. typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type
  66. param_T;
  67. template <class T> struct disable_overload{};
  68. typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type
  69. param2_T;
  70. public: // static functions
  71. using base::initialize;
  72. static int initialize(void* dest, param_T operand)
  73. {
  74. typedef typename boost::detail::make_reference_content<
  75. recursive_enabled_T
  76. >::type internal_T;
  77. new(dest) internal_T(operand);
  78. return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
  79. }
  80. static int initialize(void* dest, param2_T operand)
  81. {
  82. // This assert must newer trigger, because all the reference contents are
  83. // handled by the initilize(void* dest, param_T operand) function above
  84. BOOST_ASSERT(!is_reference_content_t::value);
  85. typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T;
  86. new(dest) value_T( boost::detail::variant::move(operand) );
  87. return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
  88. }
  89. };
  90. friend class initializer_node;
  91. public: // metafunction result
  92. typedef mpl::pair<
  93. initializer_node
  94. , typename mpl::next< index >::type
  95. > type;
  96. };
  97. };
  98. // (detail) class initializer_root
  99. //
  100. // Every level of the initializer hierarchy must expose the name
  101. // "initialize," so initializer_root provides a dummy function:
  102. //
  103. class initializer_root
  104. {
  105. public: // static functions
  106. static void initialize();
  107. };
  108. }} // namespace detail::variant
  109. } // namespace boost
  110. ///////////////////////////////////////////////////////////////////////////////
  111. // macro BOOST_VARIANT_AUX_INITIALIZER_T
  112. //
  113. // Given both the variant's typelist and a basename for forming the list of
  114. // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer
  115. // most appropriate to the current compiler.
  116. //
  117. #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
  118. ::boost::mpl::iter_fold< \
  119. mpl_seq \
  120. , ::boost::mpl::pair< \
  121. ::boost::detail::variant::initializer_root \
  122. , ::boost::mpl::int_<0> \
  123. > \
  124. , ::boost::mpl::protect< \
  125. ::boost::detail::variant::make_initializer_node \
  126. > \
  127. >::type::first \
  128. /**/
  129. #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP