File indexing completed on 2026-08-17 08:50:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_MSM_BACKMP11_METAFUNCTIONS_H
0013 #define BOOST_MSM_BACKMP11_METAFUNCTIONS_H
0014
0015 #include <boost/mp11.hpp>
0016 #include <boost/mp11/mpl_list.hpp>
0017
0018 #include <boost/mpl/copy.hpp>
0019 #include <boost/mpl/is_sequence.hpp>
0020 #include <boost/mpl/front.hpp>
0021
0022 #include <boost/type_traits/is_same.hpp>
0023 #include <boost/utility/enable_if.hpp>
0024
0025 #include <boost/msm/row_tags.hpp>
0026
0027 #include <boost/msm/backmp11/common_types.hpp>
0028 #include <boost/msm/back/traits.hpp>
0029 #include <boost/msm/front/detail/common_states.hpp>
0030
0031
0032 namespace boost { namespace msm { namespace backmp11
0033 {
0034
0035 namespace detail
0036 {
0037
0038 constexpr bool has_flag(visit_mode value, visit_mode flag)
0039 {
0040 return (static_cast<int>(value) & static_cast<int>(flag)) != 0;
0041 }
0042
0043 struct back_end_tag {};
0044
0045 template <typename T>
0046 using has_back_end_tag = std::is_same<typename T::internal::tag, back_end_tag>;
0047
0048 template <class T>
0049 using is_back_end = has_back_end_tag<T>;
0050
0051 template <typename T>
0052 using is_composite = mp11::mp_or<
0053 std::is_same<typename T::internal::tag, msm::front::detail::composite_state_tag>,
0054 has_back_end_tag<T>
0055 >;
0056
0057
0058 template <typename List, typename Func>
0059 constexpr bool for_each_until(Func&& func)
0060 {
0061 bool condition = false;
0062
0063 boost::mp11::mp_for_each<List>(
0064 [&func, &condition](auto&& item)
0065 {
0066 if (!condition)
0067 {
0068 condition = func(std::forward<decltype(item)>(item));
0069 }
0070 }
0071 );
0072 return condition;
0073 }
0074
0075
0076 template<typename T, bool C>
0077 struct optional_instance;
0078 template <typename T>
0079 struct optional_instance<T, true>
0080 {
0081 using type = T;
0082 type instance;
0083 static constexpr bool value = true;
0084 };
0085 template<typename T>
0086 struct optional_instance<T, false>
0087 {
0088 using type = T;
0089 static constexpr bool value = false;
0090 };
0091
0092
0093 template<typename T, typename Enable = void>
0094 struct to_mp_list
0095 {
0096 typedef typename mpl::copy<T, mpl::back_inserter<mp11::mp_list<>>>::type type;
0097 };
0098 template<typename T>
0099 struct to_mp_list<T, std::enable_if_t<!mpl::is_sequence<T>::value>>
0100 {
0101 using type = mp11::mp_list<T>;
0102 };
0103 template<typename ...T>
0104 struct to_mp_list<mp11::mp_list<T...>>
0105 {
0106 typedef mp11::mp_list<T...> type;
0107 };
0108 template<typename ...T>
0109 using to_mp_list_t = typename to_mp_list<T...>::type;
0110
0111 template <class stt>
0112 struct generate_state_set;
0113
0114
0115
0116
0117 template <class Stt>
0118 struct generate_state_set
0119 {
0120 typedef to_mp_list_t<Stt> stt;
0121
0122 template <typename V, typename T>
0123 using set_push_source_state =
0124 mp11::mp_set_push_back<V, typename T::current_state_type>;
0125 using source_state_set =
0126 mp11::mp_fold<stt, mp11::mp_list<>, set_push_source_state>;
0127
0128 template <typename V, typename T>
0129 using set_push_target_state =
0130 mp11::mp_set_push_back<V, typename T::next_state_type>;
0131 using state_set =
0132 mp11::mp_fold<stt, source_state_set, set_push_target_state>;
0133 };
0134
0135
0136 template <class StateSet>
0137 struct generate_state_map
0138 {
0139 typedef StateSet state_set;
0140 typedef mp11::mp_iota<mp11::mp_size<state_set>> indices;
0141 typedef mp11::mp_transform_q<
0142 mp11::mp_bind<mp11::mp_list, mp11::_1, mp11::_2>,
0143 state_set,
0144 indices
0145 > type;
0146 };
0147
0148
0149 template <class StateMap, class State>
0150 struct get_state_id
0151 {
0152 typedef mp11::mp_second<mp11::mp_map_find<
0153 StateMap,
0154 State
0155 >> type;
0156
0157 static constexpr typename type::value_type value = type::value;
0158 };
0159
0160
0161 template <class stt>
0162 struct generate_event_set
0163 {
0164 typedef to_mp_list_t<stt> stt_mp11;
0165 template<typename V, typename T>
0166 using event_set_pusher = mp11::mp_set_push_back<
0167 V,
0168 typename T::transition_event
0169 >;
0170 typedef mp11::mp_fold<
0171 to_mp_list_t<stt>,
0172 mp11::mp_list<>,
0173 event_set_pusher
0174 > event_set_mp11;
0175 };
0176
0177
0178 template <class stt>
0179 struct generate_event_map
0180 {
0181 typedef typename generate_event_set<stt>::event_set_mp11 event_set;
0182 typedef mp11::mp_iota<mp11::mp_size<event_set>> indices;
0183 typedef mp11::mp_transform_q<
0184 mp11::mp_bind<mp11::mp_list, mp11::_1, mp11::_2>,
0185 event_set,
0186 indices
0187 > type;
0188 };
0189
0190
0191 template <class stt,class Event>
0192 struct get_event_id
0193 {
0194 typedef mp11::mp_second<mp11::mp_map_find<
0195 typename generate_event_map<stt>::type,
0196 Event
0197 >> type;
0198 enum {value = type::value};
0199 };
0200
0201 template <class State>
0202 using has_state_deferred_events = mp11::mp_not<
0203 mp11::mp_empty<to_mp_list_t<typename State::deferred_events>>
0204 >;
0205
0206
0207 template< typename T1 >
0208 struct not_a_row
0209 {
0210 typedef int not_real_row_tag;
0211 struct dummy_event
0212 {
0213 };
0214 typedef T1 current_state_type;
0215 typedef T1 next_state_type;
0216 typedef dummy_event transition_event;
0217 };
0218
0219
0220
0221
0222 template <class State>
0223 struct get_wrapped_state
0224 {
0225 template <typename T>
0226 using get_wrapped_entry = typename T::wrapped_entry;
0227 using type = mp11::mp_eval_or<State, get_wrapped_entry, State>;
0228 };
0229
0230
0231 template <class Derived>
0232 struct get_transition_table
0233 {
0234 typedef typename Derived::internal::template create_real_stt<typename Derived::front_end_t>::type Stt;
0235
0236 typedef typename generate_state_set<Stt>::state_set states;
0237
0238 typedef typename Derived::internal::initial_states initial_states;
0239 template<typename V, typename T>
0240 using states_pusher = mp11::mp_if_c<
0241 mp11::mp_set_contains<states, T>::value,
0242 V,
0243 mp11::mp_push_back<
0244 V,
0245 not_a_row<typename get_wrapped_state<T>::type>
0246 >
0247 >;
0248 typedef typename mp11::mp_fold<
0249 to_mp_list_t<initial_states>,
0250 to_mp_list_t<Stt>,
0251 states_pusher
0252 > with_init;
0253
0254
0255 template<typename T>
0256 using get_explicit_creation = to_mp_list_t<typename T::explicit_creation>;
0257 using fake_explicit_created = mp11::mp_eval_or<
0258 mp11::mp_list<>,
0259 get_explicit_creation,
0260 Derived
0261 >;
0262
0263 template <class State>
0264 using convert_fake_state = mp11::mp_if_c<
0265 has_direct_entry<State>::value,
0266 typename Derived::template direct<State>,
0267 State
0268 >;
0269 using explicit_created = mp11::mp_transform<
0270 convert_fake_state,
0271 fake_explicit_created
0272 >;
0273
0274 typedef typename mp11::mp_fold<
0275 to_mp_list_t<explicit_created>,
0276 with_init,
0277 states_pusher
0278 > type;
0279 };
0280 template<typename T>
0281 using get_transition_table_t = typename get_transition_table<T>::type;
0282
0283
0284
0285 template <class State, bool IsComposite>
0286 struct recursive_get_internal_transition_table
0287 {
0288
0289 typedef typename State::front_end_t::internal_transition_table composite_table;
0290
0291 using composite_states = typename State::internal::state_set;
0292 template<typename V, typename SubState>
0293 using append_recursive_internal_transition_table = mp11::mp_append<
0294 V,
0295 typename recursive_get_internal_transition_table<SubState, has_back_end_tag<SubState>::value>::type
0296 >;
0297 typedef typename mp11::mp_fold<
0298 composite_states,
0299 to_mp_list_t<composite_table>,
0300 append_recursive_internal_transition_table
0301 > type;
0302 };
0303
0304 template <class State>
0305 struct recursive_get_internal_transition_table<State, false>
0306 {
0307 typedef to_mp_list_t<
0308 typename State::internal_transition_table
0309 > type;
0310 };
0311
0312
0313 template <class Composite>
0314 struct recursive_get_transition_table
0315 {
0316
0317 typedef typename mp11::mp_eval_if_c<
0318 !has_back_end_tag<Composite>::value,
0319 mp11::mp_list<>,
0320 get_transition_table_t,
0321 Composite
0322 > org_table;
0323
0324 typedef typename generate_state_set<org_table>::state_set states;
0325
0326
0327 template<typename V, typename T>
0328 using append_recursive_transition_table = mp11::mp_append<
0329 V,
0330 typename recursive_get_transition_table<T>::type
0331 >;
0332 typedef typename mp11::mp_fold<
0333 states,
0334 org_table,
0335 append_recursive_transition_table> type;
0336 };
0337
0338
0339 template <class State, class Event>
0340 struct direct_entry_event
0341 {
0342 public:
0343 typedef int direct_entry;
0344 typedef State active_state;
0345 typedef Event contained_event;
0346
0347 direct_entry_event(Event const& event):m_event(event){}
0348 Event const& m_event;
0349 };
0350
0351
0352
0353
0354 template <class State,class ContainingSM>
0355 struct get_owner
0356 {
0357 using type = mp11::mp_if<
0358 mp11::mp_same<typename State::owner, ContainingSM>,
0359 State,
0360 typename State::owner
0361 >;
0362 };
0363
0364
0365 template <class Sequence, class ContainingSM>
0366 struct get_fork_owner
0367 {
0368 typedef typename ::boost::mpl::front<Sequence>::type seq_front;
0369 typedef typename ::boost::mpl::if_<
0370 typename ::boost::mpl::not_<
0371 typename ::boost::is_same<typename seq_front::owner,ContainingSM>::type>::type,
0372 typename seq_front::owner,
0373 seq_front >::type type;
0374 };
0375
0376
0377 template <class State>
0378 struct get_flag_list
0379 {
0380 typedef typename mp11::mp_append<
0381 to_mp_list_t<typename State::flag_list>,
0382 to_mp_list_t<typename State::internal_flag_list>
0383 > type;
0384 };
0385
0386 template <class State>
0387 struct is_state_blocking
0388 {
0389 template<typename T>
0390 using has_event_blocking_flag = typename has_event_blocking_flag<T>::type;
0391 typedef typename mp11::mp_any_of<
0392 typename get_flag_list<State>::type,
0393 has_event_blocking_flag
0394 > type;
0395
0396 };
0397 template<typename T>
0398 using is_state_blocking_t = typename is_state_blocking<T>::type;
0399
0400 }
0401
0402 }}}
0403
0404 #endif