boost msm submachine current_state for accessing sub state - state

any idea how, using boost msm 1_60, I can get the current_state(s) of a submachine? Consider the following code, describing an outer state machine that allows for chosing between two different traffic lights (standard red, yellow, green one and another with alternating two yellow lights for instance):
class SMBigMom : public msmf::state_machine_def<SMBigMom>
{
public:
SMBigMom() {};
using initial_state = SMSelectorState;
class SMLightBase : public msmf::state_machine_def<SMLightBase>
{
public:
SMLightBase() {};
using initial_state = BaseState;
struct transition_table : mpl::vector<> {};
};
using SMBaseBackend = msm::back::state_machine<SMLightBase>;
class SMCommonRYG : public SMLightBase
{
public:
SMCommonRYG() = default;
~SMCommonRYG() {};
using initial_state = Red; // init state
struct transition_table : mpl::vector<
// Start, Event, Target, Action, Guard
msmf::Row< Red, evNext, RedYellow, msmf::none, msmf::none >,
msmf::Row< RedYellow, evNext, Green, msmf::none, msmf::none >,
msmf::Row< Green, evNext, Yellow, msmf::none, msmf::none >,
msmf::Row< Yellow, evNext, Red, msmf::none, msmf::none >
> {};
};
using SMCommonRYGBackend = msm::back::state_machine<SMCommonRYG>;
class SMYellowAlternate : public SMLightBase
{
public:
SMYellowAlternate() = default;
~SMYellowAlternate() {};
using initial_state = Yellow; // init state
struct transition_table : mpl::vector<
// Start, Event, Target, Action, Guard
msmf::Row< Yellow, evNext, Yellow2, msmf::none, msmf::none >,
msmf::Row< Yellow2, evNext, Yellow, msmf::none, msmf::none >
> {};
};
using SMYellowAlternateBackend = msm::back::state_machine<SMYellowAlternate>;
struct transition_table : mpl::vector<
msmf::Row< SMSelectorState, evSelectCommonRYG, SMCommonRYGBackend, msmf::none, msmf::none >,
msmf::Row< SMSelectorState, evSelectYellowAlternate, SMYellowAlternateBackend, msmf::none, msmf::none >
> {};
};
using SMBackend = msm::back::state_machine<SMBigMom>;
Now, I can skip into the RYG via
SMBackend oSM. oSM.process_event(evSelectCommonRYG());
But how can I get the current state of the RYG submachine?
oSM.current_state()[0]
returns 1 only (as this is the state of the outer state machine BigMom...)...
Thanks for help!

I figured it out meanwhile, the solution is rather simple. Just, using the functor front end, add an action (4th column in a ROW) function which is called like this:
struct submachineAction
{
toNext() {};
~toNext() {};
template<class TFsm, class TEvent, class TStateIn, class TStateOut>
void operator() (const TEvent& p_rEV, const TFsm& p_rFSM, TStateIn& p_rStateIn, TStateOut& p_rStateOut)
{
std::cout << "Substate: " << p_rFSM.current_state()[0] << std::endl;
}
};
If you have several "master" machines running and need to know which one called the submachineAction, you can define, for instance, a base front end class with an additional identifier (string, int, you name it) and derive the submachines from that class. Then, following this thread, you can set the identifier, which can be accessed via p_rFSM in the above functor: How to Pass data to the current boost meta state machine(MSM) substate
Hope this helps someone else sometime.

Related

Object generation from different id types slow compilation

I have a of templated class that can generate an object instance from an ID. The context is networking code with object replication.
The code below shows a way that I can manage to do this, but it has the drawback of beeing very slow in compilation.
Does anyone know a "better" way to achieve what my example shows.
I'm not sure how to make this question more clear, I hope the code speaks for itself.
I have looked at extern templates, but I do not see how to apply that to templated functions in templated classes. If anyone knows how to do that, that would solve the issue.
Alternatively a way to fix the ambiguous problem of MyRegistersSimple would also be greatly helpfull!
template<typename ID, typename Base>
class Register
{
public:
void create(ID id) { m_types.at(id).second(); }
private:
std::map<ID, std::function<std::unique_ptr<Base>(ID)>> m_types;
};
template<typename tag>
struct ID { int value; };
class ABase {};
class BBase {};
class CBase {};
using ID_A = ID<struct ID_A_TAG>;
using ID_B = ID<struct ID_B_TAG>;
using ID_C = ID<struct ID_C_TAG>;
class MyRegistersSimple :
public Register<ID_A, ABase>,
public Register<ID_B, BBase>,
public Register<ID_C, CBase>
{
};
template<typename... Registers>
class MultiRegister : public Registers...
{
public:
template<typename ID>
void create(ID)
{
// lots of complex template code to find the correct Register from 'Registers...'
// and call 'create' on it
// this makes compilation very slow
}
};
class MyRegistersComplex : public MultiRegister<
Register<ID_A, ABase>,
Register<ID_B, BBase>,
Register<ID_C, CBase>>
{};
void test()
{
MyRegistersSimple simple;
simple.create(ID_A(0)); // -> ambiguous, doest not compile
MyRegistersComplex complex;
complex.create(ID_A(0)); // -> very slow compilation
}
Basic solution
Bring all the bases into scope via using:
// a helper to avoid copy pasting `using`s
template<typename... Registers> struct MultiRegister : Registers... { using Registers::create...; };
class MyRegisters : public MultiRegister<
Register<ID_A, ABase>,
Register<ID_B, BBase>,
Register<ID_C, CBase>>
{};
void test() {
MyRegisters registers;
registers.create(ID_A(0)); // IDE shows that `Register<ID<ID_A_TAG>, ABase>` is chosen
}
I hope the built-in overload resolution is faster than "lots of complex template code" in the ...Complex version.
Offtopic improvement
I didn't like that manual Register<ID_A, ABase> ID_x <-> xBase dispatch and dummy ID_x_TAGs, so I removed all of that (if using xBase as the ID's template parameter is fine). Then Register<ID_A, ABase>, Register<ID_B, BBase> etc. become
template<typename Base> using MakeRegister = Register<ID<Base>, Base>;
and the code suggested above is just (test() omitted - it's the same)
template<typename... Registers> struct MultiRegister : Registers... { using Registers::create...; };
template<typename... Bases> using MakeMultiRegister = MultiRegister<MakeRegister<Bases>...>;
class MyRegisters : public MakeMultiRegister<ABase, BBase, CBase> {};

Conditionally creating members inside a class

Is it possible to do something like:
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
else
int newInt
};
or
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
// Nothing other wise
};
using c++17?
I would like to change the structure of a class based on some condition that can be checked at compile time. Is there any way to achieve this?
You can't use if constexpr for this. You would have to collapse them into one member using something like std::conditional:
std::conditional_t<(majorVer == 1) && (minorVer > 10), bool, int> newField;
Alternatively, you can wrap each of the two kinds of the fields in their own type:
struct A { bool newField; };
struct B { int newInt; };
And either inherit from std::conditional_t<???, A, B> or have one of those as a member.
For the case where you want either a member or nothing, the other case just needs to be an empty type. In C++20, that's:
struct E { };
[[no_unique_address]] std::conditional_t<some_condition(), bool, E> newField;
In C++17 and earlier, you'll want to inherit from this to ensure that the empty base optimization kicks in:
struct B { bool field; };
struct E { };
template <unsigned majorVer, unsigned minorVer>
class Object : private std::conditional_t<some_condition(), B, E>
{ ... };
if-constexpr is about control flow, not about memory layout. Maybe the reflection TS could be a good fit for this. However, untill that is available, you'll need other techniques.
constexpr bool useLegacyInt(unsigned major, unsigned minor)
{
return (majorVer <= 1) && (minorVer <= 10));
}
template<bool>
class ObjectBase
{
book newField;
};
template<>
class ObjectBase<true>
{
int newInt;
};
template <unsigned majorVer, unsigned minorVer>
class Object : public ObjectBase<useLegacyInt (majorVer, minorVer)>
{};
Based on this, you could do some refinements. You don't only influence the members, also the methods. So also setters and getters ... could have a different signature. Protected helper functions could provide a bool API to Object to separate the implementation.
Finally, I would not recommend using a bool, I rather expect an enumeration as this can have multiple values.
Inheriting from an earlier version could also be possible if a new version only extends. And with some default template arguments, you can even do more fancy things.
Be warned, this kind of backwards compatibility could become complex really quickly. Sometimes it's better to just copy the complete code in a legacy version and keep it as is, without interference of the new API. This at the cost of duplicated code.

boost statechart, unit-testing fraction of a state-machine

I'm looking for a way to execute (for unit-testing purposes) only fractions of a complex state -machine. For that purpose I'm evaluating boost::statechart framework.
One way that I considered was to design a hierarchical state machine, where each state is defined as a nested state-machine, that should be tested separately.
Consider the FSM definition from the following code snippet:
struct Fsm: boost::statechart::state_machine< Fsm, StateA >
{
...
}
struct StatA : boost::simple_state< StateA, Fsm, StateA1 >
{
...
}
struct StateB : boost::simple_state< StateB, Fsm, StateB1 >
{
....
}
struct StateA1 : boost::simple_state< StateA1, StateA >
{
....
}
struct StateA2 : boost::simple_state< StateA2, StateA >
{
....
}
struct StateB1 : boost::simple_state< StateB1, StateB >
{
....
}
struct StateB2 : boost::simple_state< StateB2, StateB >
{
....
}
Is it possible to unit-test the logic defined inside state B i.e. B1 and B2 inner states, without executing or even compiling the logic defined for state A including its inner A1 and A2 states?
Thanks in advance,
AmirH

decorator with a base that requires a constructor argument

I have a decorator-like pattern with a base that requires a constructor parameter. The decorator is constructed such that it can take an arbitrary number of add-on components as template parameters (up to 3 in this example).
Unfortunately, I can't figure out how to pass the base's constructor parameter to it when more than one add-on is specified. In the example below, CMyClass< AddOn_A > A( 100 ); works perfectly, but CMyClass< AddOn_A, AddOn_B > AB( 100 ); generates an error at the CMyClass constructor.
template< class Base >
class AddOn_A : public Base
{
public:
AddOn_A( int x ) : Base( x )
{
};
int AddOne()
{
return static_cast< Base* >( this )->DoSomething() + 1;
};
};
template< class Base >
class AddOn_B : public Base
{
public:
AddOn_B( int x ) : Base( x )
{
};
int AddTwo()
{
return static_cast< Base* >( this )->DoSomething() + 2;
};
};
class CBase
{
public:
explicit CBase( int x ) : x_( x )
{
};
int DoSomething()
{
return x_;
};
private:
int x_;
};
// define an empty AddOn
template< class > class empty {};
// forward declaration and Add-On defaults
template< template< class > class AddOn1 = empty,
template< class > class AddOn2 = empty,
template< class > class AddOn3 = empty >
class CMyClass;
// specialized template for the default case
template<> class CMyClass< empty, empty, empty > {};
// actual definition
template< template< class > class AddOn1,
template< class > class AddOn2,
template< class > class AddOn3 >
class CMyClass : public AddOn1< CBase >,
public CMyClass< AddOn2, AddOn3 >
{
public:
// what needs to go here???
CMyClass( int x ) : AddOn1< CBase >( x )
{};
};
int _tmain( int argc, _TCHAR* argv[] )
{
// works
CMyClass< AddOn_A > A( 100 );
_ASSERT( A.AddOne() == 101 );
// works
CMyClass< AddOn_B > B( 100 );
_ASSERT( B.AddTwo() == 102 );
// generates an error at the CMyClass ctor:
// error C2512: 'CMyClass<AddOn1>' : no appropriate default constructor available
CMyClass< AddOn_A, AddOn_B > AB( 100 );
_ASSERT( AB.AddOne() == 101 );
_ASSERT( AB.AddTwo() == 102 );
return 0;
}
If anybody can point out what I may be doing wrong, please let me know.
Thanks,
PaulH
Your errors are generally originating out of the fact that CMyClass does not have a default constructor (because you define a CMyClass(int) instead), so it is necessary to explicitly instantiate your parents with the CMyClass(int) constructor that you have. So, for example, in your definition of CMyClass you need to add the call to CMyClass(int) in the initializer list
CMyClass(int x) : AddOn1<CBase>(x), CMyClass<AddOn2, AddOn3>(x) //send x down
Now that we have CMyClass sending x down the line, it is necessary for your base case specialization (CMyClass<empty, empty, empty>) to now have a constructor that accepts x but does nothing with it
template<>
class CMyClass<empty, empty, empty> {
public:
CMyClass(int) {} //do nothing
};
Now the compiler can find the right constructors and create your classes as you expect
Just to explain why lines like CMyClass<AddOn_A> A(100) work, it's because A (in that example) has only one parent, CMyClass<empty, empty, empty>, and your specialization
template<> class CMyClass< empty, empty, empty > {};
does have a default constructor, because it's empty (or, more formally, because it defines no other constructors). This breaks down immediately once you call CMyClass<AddOn_A, AddOn_B> AB(100) because that has two parents, CMyClass<AddOn_B, empty, empty> and CMyClass<empty, empty, empty>, however the former does not have a default constructor, so the compiler does not know how to construct it. That's why we must add that one line to the initializer list, so we tell the compiler to create CMyClass<AddOn_B, empty, empty> using its CMyClass(int x) constructor (note how that means the compiler will also try to make CMyClass<empty, empty, empty> with the x parameter, so we need to add a constructor to that specialization which will accept the parameter).
It is not immediately clear what you are trying to achieve. I hope you are not mixing up inheritance and templates.
empty, AddOn_A and AddOn_B are class templates. They are not instances of a class. You need to have actual classes.

How do I invoke a non-default constructor for each inherited type from a type list?

I'm using a boost typelist to implement the policy pattern in the following manner.
using namespace boost::mpl;
template <typename PolicyTypeList = boost::mpl::vector<> >
class Host : public inherit_linearly<PolicyTypeList, inherit<_1, _2> >::type
{
public:
Host() : m_expensiveType(/* ... */) { }
private:
const ExpensiveType m_expensiveType;
};
The Host class knows how to create an instance of ExpensiveType, which is a costly operation, and each policy class exposes functionality to use it. A policy class will always minimally have the constructor defined in the following sample policy.
struct SamplePolicy
{
SamplePolicy(const ExpensiveType& expensiveType)
: m_expensiveType(expensiveType) { }
void DoSomething()
{
m_expensiveType.f();
// ...
}
private:
const ExpensiveType& m_expensiveType;
};
Is it possible to define the constructor of Host in such a way to call the constructor of each given policy? If the type list was not involved, this is very easy since the type of each policy is explicitly known.
template <typename PolicyA, typename PolicyB>
class Host : public PolicyA, public PolicyB
{
public:
Host() :
m_expensiveType(/* ... */),
PolicyA(m_expensiveType),
PolicyB(m_expensiveType) { }
private:
const ExpensiveType m_expensiveType;
};
The boost::mpl::for_each algorithm looks promising, but I can't wrap my head around how to use it to solve this problem.
If you want this kind of generation, I can only recommend a read of Alexandrescu's Modern C++ Design. There is an entire chapter dedicated to the generation of hierarchy from a typelist. You can also find it on Loki's website: Hierarchy Generators; though you will miss the diagrams and explanations, as well as the process.
For you particular problem, this seems pretty straightforward.
// Helper
struct nil
{
};
template < class Head, class Tail = nil>
struct SH: Head<Tail> /* for SimpleHierarchy */
{
SH(const ExpensiveType& e): Head(e), SH<Tail>(e) {}
};
template<>
struct SH<nil,nil>
{
SH(const ExpensiveType& e) {}
}:
// Policies
class A
{
public:
A(const ExpensiveType& e) : T(e), m_e(e) {}
private:
const ExpensiveType& m_e;
};
class B
{
public:
B(const ExpensiveType& e) : T(e), m_e(e) {}
private:
const ExpensiveType& m_e;
};
class C
{
public:
C(const ExpensiveType& e) : T(e), m_e(e) {}
private:
const ExpensiveType& m_e;
};
// Use
// nesting example
typedef SH<A, SH<B,C> > SimpleHierarchy;
// Your example, revisited
template <class A, class B>
class Host: SH<A,B>
{
public:
Host(const ExpensiveType& e): SH<A,B>(e), m_e(e) {}
private:
const ExpensiveType& m_e;
};
Of course, this is a sketch only. The main problem here is the extensibility. If you read Alexandrescu's book, you'll learn much more, and if you don't have the time, do take a peak at the source code, that might prove just what you need.
There are ways to do it directly from the mpl::vector, the only thing to realize is that you cannot do this with a big MI single-layer, but you can add many layers.
Here, I chose not to add complexity at the Policy level (they are not templatized) and to rely on MI (dual) at each level instead. You could make it purely linear, but templatizing your policies means that you cannot define them in a source file.
Also note that this approach can be adapted to take a mpl::vector directly, but this would involve the use of meta-template programming operations: back, pop_back and empty at the very least, which might obfuscate the code more than they actually help.
I could not resist the temptation to see how it could be done with inherit_linearly.
Turns out to be not that bad, IMHO:
template<class Base, class Self>
struct PolicyWrapper : Base, Self
{
PolicyWrapper(const ExpensiveType& E)
: Base(E), Self(E)
{}
};
struct EmptyWrapper
{
EmptyWrapper(const ExpensiveType& E)
{}
};
template <typename PolicyTypeList = boost::mpl::vector<> >
class Host :
public inherit_linearly<
PolicyTypeList,
PolicyWrapper<_1, _2>,
EmptyWrapper
>::type
{
typedef typename inherit_linearly<
PolicyTypeList,
PolicyWrapper<_1, _2>,
EmptyWrapper
>::type BaseType;
public:
Host() : BaseType(m_expensiveType)
{}
private:
const ExpensiveType m_expensiveType;
};
A warning though: Passing a reference to an uninitialized member like what is done in the Host ctor is very fragile.
If, for example, one writes a Policy like this:
struct BadPolicy
{
BadPolicy(const ExpensiveType& E)
: m_expensiveType(E)
{}
ExpensiveType m_expensiveType;
};
bad things will happen, as the copy ctor of ExpensiveType will be invoked with an uninitialized object.
As mentioned in the comment, you need to chain the constructor calls. For that, every type in the derivation chain has to know what type its derived from - to allow for arbitrary derivation sequences we need to make that types templates so their base can be any type.
This allows us to refer to the base and explicitly call its constructors.
I scetched out a basic example, but did end up not using boost because mpl::vector expects known types and i needed to hand it template template parameters. Instead i used a custom typelist that supports template template parameters and implicitly derives.
struct expensive {};
// derivation list
struct nil {}; // list end
struct Noop { // do nothing on end of derivation chain
Noop(expensive& e) {}
};
template<template <typename T> class H, typename L>
struct DL {
typedef L tail;
typedef H<typename tail::head> head;
};
template<template <typename T> class H>
struct DL<H, nil> {
typedef H<Noop> head;
};
// example types
template<class T>
struct A : T {
A(expensive& e) : T(e) {}
};
template<class T>
struct B : T {
B(expensive& e) : T(e) {}
};
// derivation chain usage example
typedef DL<A, DL<B, nil> > DerivationChain;
class User : DerivationChain::head
{
public:
User(expensive& e) : DerivationChain::head(e) {}
};
int main(int argc, char** argv)
{
expensive e;
User u(e);
}
Create a parameterised constructor and pass pameters to it. In this way you could acheive two things simultaneouly.
1) Constructor overloading
2) Avoid call to default constructor.