File indexing completed on 2025-01-18 09:53:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
0014 #define BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
0015
0016 #include <boost/config.hpp>
0017
0018 #include <boost/variant/detail/backup_holder.hpp>
0019 #include <boost/variant/detail/cast_storage.hpp>
0020 #include <boost/variant/detail/forced_return.hpp>
0021 #include <boost/variant/variant_fwd.hpp>
0022
0023 #include <boost/mpl/eval_if.hpp>
0024 #include <boost/mpl/bool.hpp>
0025 #include <boost/mpl/identity.hpp>
0026 #include <boost/mpl/int.hpp>
0027 #include <boost/mpl/next.hpp>
0028 #include <boost/mpl/deref.hpp>
0029 #include <boost/mpl/or.hpp>
0030 #include <boost/preprocessor/cat.hpp>
0031 #include <boost/preprocessor/inc.hpp>
0032 #include <boost/preprocessor/repeat.hpp>
0033 #include <boost/type_traits/is_same.hpp>
0034 #include <boost/type_traits/has_nothrow_copy.hpp>
0035 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
0036
0037 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0038 # pragma warning (push)
0039 # pragma warning (disable : 4702)
0040 #endif
0041
0042
0043
0044
0045
0046
0047
0048 #if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
0049
0050 # include <boost/mpl/limits/list.hpp>
0051 # define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
0052 BOOST_MPL_LIMIT_LIST_SIZE
0053
0054 #endif
0055
0056
0057 #if defined(BOOST_NO_CXX11_NULLPTR)
0058 #define BOOST_VARIANT_NULL 0
0059 #else
0060 #define BOOST_VARIANT_NULL nullptr
0061 #endif
0062
0063 namespace boost {
0064 namespace detail { namespace variant {
0065
0066
0067
0068
0069
0070
0071 struct apply_visitor_unrolled {};
0072
0073
0074
0075
0076
0077
0078
0079
0080 template <typename Iter, typename LastIter>
0081 struct visitation_impl_step
0082 {
0083 typedef typename mpl::deref<Iter>::type type;
0084
0085 typedef typename mpl::next<Iter>::type next_iter;
0086 typedef visitation_impl_step<
0087 next_iter, LastIter
0088 > next;
0089 };
0090
0091 template <typename LastIter>
0092 struct visitation_impl_step< LastIter,LastIter >
0093 {
0094 typedef apply_visitor_unrolled type;
0095 typedef visitation_impl_step next;
0096 };
0097
0098
0099
0100
0101
0102
0103
0104
0105 template <typename Visitor, typename VoidPtrCV, typename T>
0106 inline typename Visitor::result_type
0107 visitation_impl_invoke_impl(
0108 int, Visitor& visitor, VoidPtrCV storage, T*
0109 , mpl::true_
0110 )
0111 {
0112 return visitor.internal_visit(
0113 cast_storage<T>(storage), 1L
0114 );
0115 }
0116
0117 template <typename Visitor, typename VoidPtrCV, typename T>
0118 inline typename Visitor::result_type
0119 visitation_impl_invoke_impl(
0120 int internal_which, Visitor& visitor, VoidPtrCV storage, T*
0121 , mpl::false_
0122 )
0123 {
0124 if (internal_which >= 0)
0125 {
0126 return visitor.internal_visit(
0127 cast_storage<T>(storage), 1L
0128 );
0129 }
0130 else
0131 {
0132 return visitor.internal_visit(
0133 cast_storage< backup_holder<T> >(storage), 1L
0134 );
0135 }
0136 }
0137
0138 template <typename Visitor, typename VoidPtrCV, typename T, typename NoBackupFlag>
0139 inline typename Visitor::result_type
0140 visitation_impl_invoke(
0141 int internal_which, Visitor& visitor, VoidPtrCV storage, T* t
0142 , NoBackupFlag
0143 , int
0144 )
0145 {
0146 typedef typename mpl::or_<
0147 NoBackupFlag
0148 , is_nothrow_move_constructible<T>
0149 , has_nothrow_copy<T>
0150 >::type never_uses_backup;
0151
0152 return (visitation_impl_invoke_impl)(
0153 internal_which, visitor, storage, t
0154 , never_uses_backup()
0155 );
0156 }
0157
0158 template <typename Visitor, typename VoidPtrCV, typename NBF>
0159 inline typename Visitor::result_type
0160 visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long)
0161 {
0162
0163 typedef typename Visitor::result_type result_type;
0164 return ::boost::detail::variant::forced_return< result_type >();
0165 }
0166
0167
0168
0169
0170
0171
0172
0173 template <
0174 typename W, typename S
0175 , typename Visitor, typename VPCV
0176 , typename NBF
0177 >
0178 inline typename Visitor::result_type
0179 visitation_impl(
0180 int, int, Visitor&, VPCV
0181 , mpl::true_
0182 , NBF, W* = BOOST_VARIANT_NULL, S* = BOOST_VARIANT_NULL
0183 )
0184 {
0185
0186 typedef typename Visitor::result_type result_type;
0187 return ::boost::detail::variant::forced_return< result_type >();
0188 }
0189
0190 template <
0191 typename Which, typename step0
0192 , typename Visitor, typename VoidPtrCV
0193 , typename NoBackupFlag
0194 >
0195 BOOST_FORCEINLINE typename Visitor::result_type
0196 visitation_impl(
0197 const int internal_which, const int logical_which
0198 , Visitor& visitor, VoidPtrCV storage
0199 , mpl::false_
0200 , NoBackupFlag no_backup_flag
0201 , Which* = BOOST_VARIANT_NULL, step0* = BOOST_VARIANT_NULL
0202 )
0203 {
0204
0205 # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \
0206 typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \
0207 typedef typename BOOST_PP_CAT(step,N)::next \
0208 BOOST_PP_CAT(step, BOOST_PP_INC(N)); \
0209
0210
0211 BOOST_PP_REPEAT(
0212 BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
0213 , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
0214 , _
0215 )
0216
0217 # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
0218
0219
0220 switch (logical_which)
0221 {
0222
0223
0224 # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \
0225 case (Which::value + (N)): \
0226 return (visitation_impl_invoke)( \
0227 internal_which, visitor, storage \
0228 , static_cast<BOOST_PP_CAT(T,N)*>(0) \
0229 , no_backup_flag, 1L \
0230 ); \
0231
0232
0233 BOOST_PP_REPEAT(
0234 BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
0235 , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
0236 , _
0237 )
0238
0239 # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
0240
0241 default: break;
0242 }
0243
0244
0245 typedef mpl::int_<
0246 Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
0247 > next_which;
0248
0249 typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
0250 next_step;
0251
0252 typedef typename next_step::type next_type;
0253 typedef typename is_same< next_type,apply_visitor_unrolled >::type
0254 is_apply_visitor_unrolled;
0255
0256 return detail::variant::visitation_impl(
0257 internal_which, logical_which
0258 , visitor, storage
0259 , is_apply_visitor_unrolled()
0260 , no_backup_flag
0261 , static_cast<next_which*>(0), static_cast<next_step*>(0)
0262 );
0263 }
0264
0265 }}
0266 }
0267
0268 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0269 # pragma warning(pop)
0270 #endif
0271
0272 #endif