visitation_impl.hpp 8.6 KB

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