visitation_impl.hpp 7.9 KB

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