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