visitation_impl.hpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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/detail/generic_result_type.hpp"
  19. #include "boost/variant/variant_fwd.hpp" // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
  20. #include "boost/mpl/eval_if.hpp"
  21. #include "boost/mpl/bool.hpp"
  22. #include "boost/mpl/identity.hpp"
  23. #include "boost/mpl/int.hpp"
  24. #include "boost/mpl/next.hpp"
  25. #include "boost/mpl/deref.hpp"
  26. #include "boost/mpl/or.hpp"
  27. #include "boost/preprocessor/cat.hpp"
  28. #include "boost/preprocessor/inc.hpp"
  29. #include "boost/preprocessor/repeat.hpp"
  30. #include "boost/type_traits/is_same.hpp"
  31. #include "boost/type_traits/has_nothrow_copy.hpp"
  32. #include "boost/type_traits/is_nothrow_move_constructible.hpp"
  33. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  34. # pragma warning (push)
  35. # pragma warning (disable : 4702) //unreachable code
  36. #endif
  37. ///////////////////////////////////////////////////////////////////////////////
  38. // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  39. //
  40. // Unrolls variant's visitation mechanism to reduce template instantiation
  41. // and potentially increase runtime performance. (TODO: Investigate further.)
  42. //
  43. #if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  44. #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
  45. # include "boost/mpl/limits/list.hpp"
  46. # define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
  47. BOOST_MPL_LIMIT_LIST_SIZE
  48. #else
  49. # define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
  50. BOOST_VARIANT_LIMIT_TYPES
  51. #endif
  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
  88. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
  89. visitation_impl_invoke_impl(
  90. int, Visitor& visitor, VoidPtrCV storage, T*
  91. , mpl::true_// never_uses_backup
  92. )
  93. {
  94. return visitor.internal_visit(
  95. cast_storage<T>(storage), 1L
  96. );
  97. }
  98. template <typename Visitor, typename VoidPtrCV, typename T>
  99. inline
  100. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
  101. visitation_impl_invoke_impl(
  102. int internal_which, Visitor& visitor, VoidPtrCV storage, T*
  103. , mpl::false_// never_uses_backup
  104. )
  105. {
  106. if (internal_which >= 0)
  107. {
  108. return visitor.internal_visit(
  109. cast_storage<T>(storage), 1L
  110. );
  111. }
  112. else
  113. {
  114. return visitor.internal_visit(
  115. cast_storage< backup_holder<T> >(storage), 1L
  116. );
  117. }
  118. }
  119. template <typename Visitor, typename VoidPtrCV, typename T, typename NoBackupFlag>
  120. inline
  121. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
  122. visitation_impl_invoke(
  123. int internal_which, Visitor& visitor, VoidPtrCV storage, T* t
  124. , NoBackupFlag
  125. , int
  126. )
  127. {
  128. typedef typename mpl::or_<
  129. NoBackupFlag
  130. , is_nothrow_move_constructible<T>
  131. , has_nothrow_copy<T>
  132. >::type never_uses_backup;
  133. return (visitation_impl_invoke_impl)(
  134. internal_which, visitor, storage, t
  135. , never_uses_backup()
  136. );
  137. }
  138. template <typename Visitor, typename VoidPtrCV, typename NBF>
  139. inline
  140. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
  141. visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long)
  142. {
  143. // should never be here at runtime!
  144. typedef typename Visitor::result_type result_type;
  145. return ::boost::detail::variant::forced_return< result_type >();
  146. }
  147. ///////////////////////////////////////////////////////////////////////////////
  148. // (detail) function template visitation_impl
  149. //
  150. // Invokes the given visitor on the type in the given variant storage.
  151. //
  152. template <
  153. typename W, typename S
  154. , typename Visitor, typename VPCV
  155. , typename NBF
  156. >
  157. inline
  158. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
  159. visitation_impl(
  160. int, int, Visitor&, VPCV
  161. , mpl::true_ // is_apply_visitor_unrolled
  162. , NBF, W* = 0, S* = 0
  163. )
  164. {
  165. // should never be here at runtime!
  166. typedef typename Visitor::result_type result_type;
  167. return ::boost::detail::variant::forced_return< result_type >();
  168. }
  169. template <
  170. typename Which, typename step0
  171. , typename Visitor, typename VoidPtrCV
  172. , typename NoBackupFlag
  173. >
  174. inline
  175. BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
  176. visitation_impl(
  177. const int internal_which, const int logical_which
  178. , Visitor& visitor, VoidPtrCV storage
  179. , mpl::false_ // is_apply_visitor_unrolled
  180. , NoBackupFlag no_backup_flag
  181. , Which* = 0, step0* = 0
  182. )
  183. {
  184. // Typedef apply_visitor_unrolled steps and associated types...
  185. # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \
  186. typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \
  187. typedef typename BOOST_PP_CAT(step,N)::next \
  188. BOOST_PP_CAT(step, BOOST_PP_INC(N)); \
  189. /**/
  190. BOOST_PP_REPEAT(
  191. BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  192. , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
  193. , _
  194. )
  195. # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
  196. // ...switch on the target which-index value...
  197. switch (logical_which)
  198. {
  199. // ...applying the appropriate case:
  200. # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \
  201. case (Which::value + (N)): \
  202. return (visitation_impl_invoke)( \
  203. internal_which, visitor, storage \
  204. , static_cast<BOOST_PP_CAT(T,N)*>(0) \
  205. , no_backup_flag, 1L \
  206. ); \
  207. /**/
  208. BOOST_PP_REPEAT(
  209. BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  210. , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
  211. , _
  212. )
  213. # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
  214. default: break;
  215. }
  216. // If not handled in this iteration, continue unrolling:
  217. typedef mpl::int_<
  218. Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  219. > next_which;
  220. typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
  221. next_step;
  222. typedef typename next_step::type next_type;
  223. typedef typename is_same< next_type,apply_visitor_unrolled >::type
  224. is_apply_visitor_unrolled;
  225. return visitation_impl(
  226. internal_which, logical_which
  227. , visitor, storage
  228. , is_apply_visitor_unrolled()
  229. , no_backup_flag
  230. , static_cast<next_which*>(0), static_cast<next_step*>(0)
  231. );
  232. }
  233. }} // namespace detail::variant
  234. } // namespace boost
  235. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  236. # pragma warning(pop)
  237. #endif
  238. #endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP