visitation_impl.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. namespace boost {
  48. namespace detail { namespace variant {
  49. ///////////////////////////////////////////////////////////////////////////////
  50. // (detail) class apply_visitor_unrolled
  51. //
  52. // Tag type indicates when visitation_impl is unrolled.
  53. //
  54. struct apply_visitor_unrolled {};
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // (detail) class template visitation_impl_step
  57. //
  58. // "Never ending" iterator range facilitates visitation_impl unrolling.
  59. //
  60. template <typename Iter, typename LastIter>
  61. struct visitation_impl_step
  62. {
  63. typedef typename mpl::deref<Iter>::type type;
  64. typedef typename mpl::next<Iter>::type next_iter;
  65. typedef visitation_impl_step<
  66. next_iter, LastIter
  67. > next;
  68. };
  69. template <typename LastIter>
  70. struct visitation_impl_step< LastIter,LastIter >
  71. {
  72. typedef apply_visitor_unrolled type;
  73. typedef visitation_impl_step next;
  74. };
  75. ///////////////////////////////////////////////////////////////////////////////
  76. // (detail) function template visitation_impl_invoke
  77. //
  78. // Invokes the given visitor on the specified type in the given storage.
  79. //
  80. template <typename Visitor, typename VoidPtrCV, typename T>
  81. inline typename Visitor::result_type
  82. visitation_impl_invoke_impl(
  83. int, Visitor& visitor, VoidPtrCV storage, T*
  84. , mpl::true_// never_uses_backup
  85. )
  86. {
  87. return visitor.internal_visit(
  88. cast_storage<T>(storage), 1L
  89. );
  90. }
  91. template <typename Visitor, typename VoidPtrCV, typename T>
  92. inline typename Visitor::result_type
  93. visitation_impl_invoke_impl(
  94. int internal_which, Visitor& visitor, VoidPtrCV storage, T*
  95. , mpl::false_// never_uses_backup
  96. )
  97. {
  98. if (internal_which >= 0)
  99. {
  100. return visitor.internal_visit(
  101. cast_storage<T>(storage), 1L
  102. );
  103. }
  104. else
  105. {
  106. return visitor.internal_visit(
  107. cast_storage< backup_holder<T> >(storage), 1L
  108. );
  109. }
  110. }
  111. template <typename Visitor, typename VoidPtrCV, typename T, typename NoBackupFlag>
  112. inline typename Visitor::result_type
  113. visitation_impl_invoke(
  114. int internal_which, Visitor& visitor, VoidPtrCV storage, T* t
  115. , NoBackupFlag
  116. , int
  117. )
  118. {
  119. typedef typename mpl::or_<
  120. NoBackupFlag
  121. , is_nothrow_move_constructible<T>
  122. , has_nothrow_copy<T>
  123. >::type never_uses_backup;
  124. return (visitation_impl_invoke_impl)(
  125. internal_which, visitor, storage, t
  126. , never_uses_backup()
  127. );
  128. }
  129. template <typename Visitor, typename VoidPtrCV, typename NBF>
  130. inline typename Visitor::result_type
  131. visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long)
  132. {
  133. // should never be here at runtime!
  134. typedef typename Visitor::result_type result_type;
  135. return ::boost::detail::variant::forced_return< result_type >();
  136. }
  137. ///////////////////////////////////////////////////////////////////////////////
  138. // (detail) function template visitation_impl
  139. //
  140. // Invokes the given visitor on the type in the given variant storage.
  141. //
  142. template <
  143. typename W, typename S
  144. , typename Visitor, typename VPCV
  145. , typename NBF
  146. >
  147. inline typename Visitor::result_type
  148. visitation_impl(
  149. int, int, Visitor&, VPCV
  150. , mpl::true_ // is_apply_visitor_unrolled
  151. , NBF, W* = nullptr, S* = nullptr
  152. )
  153. {
  154. // should never be here at runtime!
  155. typedef typename Visitor::result_type result_type;
  156. return ::boost::detail::variant::forced_return< result_type >();
  157. }
  158. template <
  159. typename Which, typename step0
  160. , typename Visitor, typename VoidPtrCV
  161. , typename NoBackupFlag
  162. >
  163. BOOST_FORCEINLINE typename Visitor::result_type
  164. visitation_impl(
  165. const int internal_which, const int logical_which
  166. , Visitor& visitor, VoidPtrCV storage
  167. , mpl::false_ // is_apply_visitor_unrolled
  168. , NoBackupFlag no_backup_flag
  169. , Which* = nullptr, step0* = nullptr
  170. )
  171. {
  172. // Typedef apply_visitor_unrolled steps and associated types...
  173. # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \
  174. typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \
  175. typedef typename BOOST_PP_CAT(step,N)::next \
  176. BOOST_PP_CAT(step, BOOST_PP_INC(N)); \
  177. /**/
  178. BOOST_PP_REPEAT(
  179. BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  180. , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
  181. , _
  182. )
  183. # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
  184. // ...switch on the target which-index value...
  185. switch (logical_which)
  186. {
  187. // ...applying the appropriate case:
  188. # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \
  189. case (Which::value + (N)): \
  190. return (visitation_impl_invoke)( \
  191. internal_which, visitor, storage \
  192. , static_cast<BOOST_PP_CAT(T,N)*>(0) \
  193. , no_backup_flag, 1L \
  194. ); \
  195. /**/
  196. BOOST_PP_REPEAT(
  197. BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  198. , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
  199. , _
  200. )
  201. # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
  202. default: break;
  203. }
  204. // If not handled in this iteration, continue unrolling:
  205. typedef mpl::int_<
  206. Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  207. > next_which;
  208. typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  209. next_step;
  210. typedef typename next_step::type next_type;
  211. typedef typename is_same< next_type,apply_visitor_unrolled >::type
  212. is_apply_visitor_unrolled;
  213. return detail::variant::visitation_impl(
  214. internal_which, logical_which
  215. , visitor, storage
  216. , is_apply_visitor_unrolled()
  217. , no_backup_flag
  218. , static_cast<next_which*>(0), static_cast<next_step*>(0)
  219. );
  220. }
  221. }} // namespace detail::variant
  222. } // namespace boost
  223. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  224. # pragma warning(pop)
  225. #endif
  226. #endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP