diff --git a/README.md b/README.md new file mode 100644 index 0000000..94007c8 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# msm +Boost.org msm module +[Please look at the generated documentation](http://htmlpreview.github.com/?https://github.com/boostorg/msm/blob/master/doc/HTML/index.html) +You might need to force browser reloading (F5) diff --git a/include/boost/msm/back/state_machine.hpp b/include/boost/msm/back/state_machine.hpp index 9c0a3e7..002c7f9 100644 --- a/include/boost/msm/back/state_machine.hpp +++ b/include/boost/msm/back/state_machine.hpp @@ -78,6 +78,14 @@ BOOST_MPL_HAS_XXX_TRAIT_DEF(compile_policy) BOOST_MPL_HAS_XXX_TRAIT_DEF(queue_container_policy) BOOST_MPL_HAS_XXX_TRAIT_DEF(using_declared_table) +#ifndef BOOST_MSM_FORCE_PP +# ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES +# ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_MSM_INTERNAL_USE_VARIADIC_TEMPLATES +# endif +# endif +#endif + #ifndef BOOST_MSM_CONSTRUCTOR_ARG_SIZE #define BOOST_MSM_CONSTRUCTOR_ARG_SIZE 5 // default max number of arguments for constructors #endif @@ -1597,6 +1605,45 @@ class state_machine : //public Derived // create states fill_states(this); } +#ifdef BOOST_MSM_INTERNAL_USE_VARIADIC_TEMPLATES + template::type>::type> + state_machine(FirstArg&& first, Args&&... args) + : Derived(std::forward(first), std::forward(args)...), + m_events_queue(), + m_deferred_events_queue(), + m_history(), + m_event_processing(false), + m_is_included(false), + m_visitors(), + m_substate_list() + { + ::boost::mpl::for_each >(init_states(m_states)); + m_history.set_initial_states(m_states); + fill_states(this); + } + + template::type>::type> + state_machine(Expr expr, Args&&... args) + : Derived(std::forward(args)...), + m_events_queue(), + m_deferred_events_queue(), + m_history(), + m_event_processing(false), + m_is_included(false), + m_visitors(), + m_substate_list() + { + BOOST_MPL_ASSERT_MSG((::boost::proto::matches::value), + THE_STATES_EXPRESSION_PASSED_DOES_NOT_MATCH_GRAMMAR, (FoldToList)); + + ::boost::mpl::for_each >(init_states(m_states)); + m_history.set_initial_states(m_states); + set_states(expr); + fill_states(this); + } +#else template state_machine (Expr const& expr,typename ::boost::enable_if::type >::type* =0) @@ -1670,6 +1717,7 @@ class state_machine : //public Derived BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_ADD(BOOST_MSM_CONSTRUCTOR_ARG_SIZE,1), MSM_CONSTRUCTOR_HELPER_EXECUTE, ~) #undef MSM_CONSTRUCTOR_HELPER_EXECUTE #undef MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index af7aad0..c8b6068 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -11,13 +11,15 @@ import testing ; project msm : requirements - . + . gcc:"-ftemplate-depth-300 -g0" darwin:"-ftemplate-depth-300 -g0" intel:"-g0" + clang:"-g0" gcc:off darwin:off intel:off + clang:off /boost/test//boost_unit_test_framework/static /boost/serialization//boost_serialization/static ; @@ -47,3 +49,4 @@ test-suite msm-unit-tests [ run TestConstructor.cpp ] ; +unit-test TestConstructorMovableOnlyTypes : TestConstructorMovableOnlyTypes.cpp : -std=c++14 ; diff --git a/test/TestConstructorMovableOnlyTypes.cpp b/test/TestConstructorMovableOnlyTypes.cpp new file mode 100644 index 0000000..f45b6f1 --- /dev/null +++ b/test/TestConstructorMovableOnlyTypes.cpp @@ -0,0 +1,118 @@ +// Copyright 2016 BogumiƂ Chojnowski +// bogumil DOT chojnowski AT gmail DOT com +// This is extended version of the state machine available in the boost::mpl library +// Distributed under the same license as the original. +// Copyright for the original version: +// Copyright 2010 Christophe Henry +// henry UNDERSCORE christophe AT hotmail DOT com +// This is an extended version of the state machine available in the boost::mpl library +// Distributed under the same license as the original. +// Copyright for the original version: +// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed +// under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +// back-end +#include +//front-end +#include +#ifndef BOOST_MSM_NONSTANDALONE_TEST +#define BOOST_TEST_MODULE MyTest +#endif +#include + +namespace msm = boost::msm; +namespace mpl = boost::mpl; + + +namespace +{ + struct Lightbulp + { + Lightbulp(int c) : current(c) {} + int current; + }; + + // events + struct ev_toggle {}; + + // front-end: define the FSM structure + struct bistable_switch_ : public msm::front::state_machine_def + { + bistable_switch_(std::unique_ptr bulp, int load) + : bulp_(std::move(bulp)) + { + BOOST_CHECK_MESSAGE(bulp_->current == 3, "Wrong current value"); + BOOST_CHECK_MESSAGE(load == 5, "Wrong load value"); + bulp_->current = 10; + } + + std::unique_ptr bulp_; + + // The list of FSM states + struct Off : public msm::front::state<> + { + template + void on_entry(Event const&, FSM& fsm) { std::cout << "entering: Off" << std::endl; } + template + void on_exit(Event const&, FSM&) { std::cout << "leaving: Off" << std::endl; } + }; + + struct On : public msm::front::state<> + { + template + void on_entry(Event const&, FSM& fsm) { std::cout << "entering: On" << std::endl; } + template + void on_exit(Event const&, FSM&) { std::cout << "leaving: On" << std::endl; } + }; + + // the initial state of the player SM. Must be defined + typedef Off initial_state; + + void turn_on(ev_toggle const&) { bulp_->current = 11; std::cout << "bistable_switch::turn_on" << std::endl; } + void turn_off(ev_toggle const&) { bulp_->current = 9; std::cout << "bistable_switch::turn_off" << std::endl; } + + typedef bistable_switch_ bs_; // makes transition table cleaner + + // Transition table for player + struct transition_table : mpl::vector< + // Start Event Next Action Guard + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Off , ev_toggle , On , &bs_::turn_on >, + a_row < On , ev_toggle , Off , &bs_::turn_off > + // +---------+-------------+---------+---------------------+----------------------+ + > {}; + // Replaces the default no-transition response. + + template + void no_transition(Event const&, FSM&, int) + { + BOOST_FAIL("no_transition called!"); + } + }; + + // Pick a back-end + typedef msm::back::state_machine bistable_switch; + + BOOST_AUTO_TEST_CASE(my_test) + { + auto bulp = std::make_unique(3); + + bistable_switch bs(std::move(bulp), 5); + BOOST_CHECK_MESSAGE(bs.bulp_->current == 10, "Wrong returned current value"); + + bs.start(); + + bs.process_event(ev_toggle()); + BOOST_CHECK_MESSAGE(bs.bulp_->current == 11, "Wrong returned current value"); + + bs.process_event(ev_toggle()); + BOOST_CHECK_MESSAGE(bs.bulp_->current == 9, "Wrong returned current value"); + + bs.stop(); + } +} +