visitation_impl.hpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. //-----------------------------------------------------------------------------
  2. // boost variant/detail/visitation_impl.hpp header file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2003
  7. // Eric Friedman
  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_VISITATION_IMPL_HPP
  13. #define BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
  14. #include <boost/config.hpp>
  15. #include <boost/variant/detail/backup_holder.hpp>
  16. #include <boost/variant/detail/cast_storage.hpp>
  17. #include <boost/variant/detail/forced_return.hpp>
  18. #include <boost/variant/variant_fwd.hpp>
  19. #include <boost/mpl/eval_if.hpp>
  20. #include <boost/mpl/bool.hpp>
  21. #include <boost/mpl/identity.hpp>
  22. #include <boost/mpl/int.hpp>
  23. #include <boost/mpl/next.hpp>
  24. #include <boost/mpl/deref.hpp>
  25. #include <boost/mpl/or.hpp>
  26. #include <boost/preprocessor/cat.hpp>
  27. #include <boost/preprocessor/inc.hpp>
  28. #include <boost/preprocessor/repeat.hpp>
  29. #include <boost/type_traits/is_same.hpp>
  30. #include <boost/type_traits/has_nothrow_copy.hpp>
  31. #include <boost/type_traits/is_nothrow_move_constructible.hpp>
  32. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  33. # pragma warning (push)
  34. # pragma warning (disable : 4702) //unreachable code
  35. #endif
  36. ///////////////////////////////////////////////////////////////////////////////
  37. // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  38. //
  39. // Unrolls variant's visitation mechanism to reduce template instantiation
  40. // and potentially increase runtime performance. (TODO: Investigate further.)
  41. //
  42. #if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  43. # include <boost/mpl/limits/list.hpp>
  44. # define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
  45. BOOST_MPL_LIMIT_LIST_SIZE
  46. #endif
  47. // Define a compiler generic null pointer value
  48. #if defined(BOOST_NO_CXX11_NULLPTR)
  49. #define BOOST_VARIANT_NULL 0
  50. #else
  51. #define BOOST_VARIANT_NULL nullptr
  52. #endif
  53. namespace boost {
  54. namespace detail { namespace variant {
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // (detail) class apply_visitor_unrolled
  57. //
  58. // Tag type indicates when visitation_impl is unrolled.
  59. //
  60. struct apply_visitor_unrolled {};
  61. ///////////////////////////////////////////////////////////////////////////////
  62. // (detail) class template visitation_impl_step
  63. //
  64. // "Never ending" iterator range facilitates visitation_impl unrolling.
  65. //
  66. template <typename Iter, typename LastIter>
  67. struct visitation_impl_step
  68. {
  69. typedef typename mpl::deref<Iter>::type type;
  70. typedef typename mpl::next<Iter>::type next_iter;
  71. typedef visitation_impl_step<
  72. next_iter, LastIter
  73. > next;
  74. };
  75. template <typename LastIter>
  76. struct visitation_impl_step< LastIter,LastIter >
  77. {
  78. typedef apply_visitor_unrolled type;
  79. typedef visitation_impl_step next;
  80. };
  81. ///////////////////////////////////////////////////////////////////////////////
  82. // (detail) function template visitation_impl_invoke
  83. //
  84. // Invokes the given visitor on the specified type in the given storage.
  85. //
  86. template <typename Visitor, typename VoidPtrCV, typename T>
  87. inline typename Visitor::result_type
  88. visitation_impl_invoke_impl(
  89. int, Visitor& visitor, VoidPtrCV storage, T*
  90. , mpl::true_// never_uses_backup
  91. )
  92. {
  93. return visitor.internal_visit(
  94. cast_storage<T>(storage), 1L
  95. );
  96. }
  97. template <typename Visitor, typename VoidPtrCV, typename T>
  98. inline typename Visitor::result_type
  99. visitation_impl_invoke_impl(
  100. int internal_which, Visitor& visitor, VoidPtrCV storage, T*
  101. , mpl::false_// never_uses_backup
  102. )
  103. {
  104. if (internal_which >= 0)
  105. {
  106. return visitor.internal_visit(
  107. cast_storage<T>(storage), 1L
  108. );
  109. }
  110. else
  111. {
  112. return visitor.internal_visit(
  113. cast_storage< backup_holder<T> >(storage), 1L
  114. );
  115. }
  116. }
  117. template <typename Visitor, typename VoidPtrCV, typename T, typename NoBackupFlag>
  118. inline typename Visitor::result_type
  119. visitation_impl_invoke(
  120. int internal_which, Visitor& visitor, VoidPtrCV storage, T* t
  121. , NoBackupFlag
  122. , int
  123. )
  124. {
  125. typedef typename mpl::or_<
  126. NoBackupFlag
  127. , is_nothrow_move_constructible<T>
  128. , has_nothrow_copy<T>
  129. >::type never_uses_backup;
  130. return (visitation_impl_invoke_impl)(
  131. internal_which, visitor, storage, t
  132. , never_uses_backup()
  133. );
  134. }
  135. template <typename Visitor, typename VoidPtrCV, typename NBF>
  136. inline typename Visitor::result_type
  137. visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long)
  138. {
  139. // should never be here at runtime!
  140. typedef typename Visitor::result_type result_type;
  141. return ::boost::detail::variant::forced_return< result_type >();
  142. }
  143. ///////////////////////////////////////////////////////////////////////////////
  144. // (detail) function template visitation_impl
  145. //
  146. // Invokes the given visitor on the type in the given variant storage.
  147. //
  148. template <
  149. typename W, typename S
  150. , typename Visitor, typename VPCV
  151. , typename NBF
  152. >
  153. inline typename Visitor::result_type
  154. visitation_impl(
  155. int, int, Visitor&, VPCV
  156. , mpl::true_ // is_apply_visitor_unrolled
  157. , NBF, W* = BOOST_VARIANT_NULL, S* = BOOST_VARIANT_NULL
  158. )
  159. {
  160. // should never be here at runtime!
  161. typedef typename Visitor::result_type result_type;
  162. return ::boost::detail::variant::forced_return< result_type >();
  163. }
  164. template <
  165. typename Which, typename step0
  166. , typename Visitor, typename VoidPtrCV
  167. , typename NoBackupFlag
  168. >
  169. BOOST_FORCEINLINE typename Visitor::result_type
  170. visitation_impl(
  171. const int internal_which, const int logical_which
  172. , Visitor& visitor, VoidPtrCV storage
  173. , mpl::false_ // is_apply_visitor_unrolled
  174. , NoBackupFlag no_backup_flag
  175. , Which* = BOOST_VARIANT_NULL, step0* = BOOST_VARIANT_NULL
  176. )
  177. {
  178. // Typedef apply_visitor_unrolled steps and associated types...
  179. # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \
  180. typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \
  181. typedef typename BOOST_PP_CAT(step,N)::next \
  182. BOOST_PP_CAT(step, BOOST_PP_INC(N)); \
  183. /**/
  184. BOOST_PP_REPEAT(
  185. BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  186. , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
  187. , _
  188. )
  189. # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
  190. // ...switch on the target which-index value...
  191. switch (logical_which)
  192. {
  193. // ...applying the appropriate case:
  194. # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \
  195. case (Which::value + (N)): \
  196. return (visitation_impl_invoke)( \
  197. internal_which, visitor, storage \
  198. , static_cast<BOOST_PP_CAT(T,N)*>(0) \
  199. , no_backup_flag, 1L \
  200. ); \
  201. /**/
  202. BOOST_PP_REPEAT(
  203. BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  204. , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
  205. , _
  206. )
  207. # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
  208. default: break;
  209. }
  210. // If not handled in this iteration, continue unrolling:
  211. typedef mpl::int_<
  212. Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  213. > next_which;
  214. typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  215. next_step;
  216. typedef typename next_step::type next_type;
  217. typedef typename is_same< next_type,apply_visitor_unrolled >::type
  218. is_apply_visitor_unrolled;
  219. return detail::variant::visitation_impl(
  220. internal_which, logical_which
  221. , visitor, storage
  222. , is_apply_visitor_unrolled()
  223. , no_backup_flag
  224. , static_cast<next_which*>(0), static_cast<next_step*>(0)
  225. );
  226. }
  227. }} // namespace detail::variant
  228. } // namespace boost
  229. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  230. # pragma warning(pop)
  231. #endif
  232. #endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP