I am really sorry but first version of this code is incorrect. For each call of init, run and stop new objects worker1 and worker2 are created (each time constructor os worker1 and worker2 called). So m_t3 variable is useless.
Bellow is correct code. As you may see constructors of worker1 and worker2 are called one time.
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
struct worker1
{
worker1()
{
std::cout << "Worker1 ctor" << std::endl;
}
void init()
{
std::cout << "Worker1 init called. Object address [" << this << "]" << std::endl;
}
void run()
{
std::cout << "Worker1 run called. Object address [" << this << "]" << std::endl;
}
void stop()
{
std::cout << "Worker1 stop called. Object address [" << this << "]" << std::endl;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
struct worker2
{
worker2()
{
std::cout << "Worker2 ctor" << std::endl;
}
void init()
{
std::cout << "Worker2 init called. Object address [" << this << "]" << std::endl;
}
void run()
{
std::cout << "Worker2 run called. Object address [" << this << "]" << std::endl;
}
void stop()
{
std::cout << "Worker2 stop called. Object address [" << this << "]" << std::endl;
}
};
typedef mpl::vector< worker1, worker2 > workers;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
template< typename U> struct process3
{
process3()
{
factory();
}
struct factoryrun
{
template< typename T > void operator()(T& x)
{
std::cout << "Factory entry" << std::endl;
std::cout << "Type is = " << typeid( T ).name() << std::endl;
m_t3.push_back( x );
}
};
void init()
{
static init_visitor vis;
std::for_each( m_t3.begin(), m_t3.end(), boost::apply_visitor( vis ) );
}
void run()
{
static run_visitor vis;
std::for_each( m_t3.begin(), m_t3.end(), boost::apply_visitor( vis ) );
}
void stop()
{
static stop_visitor vis;
std::for_each( m_t3.begin(), m_t3.end(), boost::apply_visitor( vis ) );
}
typedef typename boost::make_variant_over< U >::type types;
typedef std::vector<types> Vector; // Make typedef to simplify
static Vector m_t3;
struct init_visitor: public boost::static_visitor<>
{
template <typename T>
void operator()( T& x )
{
std::cout << "Init visitor type=" << typeid(x).name() << std::endl;
x.init();
}
};
struct run_visitor: public boost::static_visitor<>
{
template <typename T>
void operator()( T& x )
{
std::cout << "Run visitor type=" << typeid(x).name() << std::endl;
x.run();
}
};
struct stop_visitor: public boost::static_visitor<>
{
template <typename T>
void operator()( T& x )
{
std::cout << "Stop visitor type=" << typeid(x).name() << std::endl;
x.stop();
}
};
};
template<typename K> typename process3<K>::Vector process3<K>::m_t3;
int main() {
process3<workers> prs3;
prs3.init();
prs3.run();
prs3.stop();
return 0;
}
Output:
Factory start
Worker1 ctor
Factory entry
Type is = 7worker1
Worker2 ctor
Factory entry
Type is = 7worker2
Init visitor type=7worker1
Worker1 init called. Object address [0x21bf038]
Init visitor type=7worker2
Worker2 init called. Object address [0x21bf048]
Run visitor type=7worker1
Worker1 run called. Object address [0x21bf038]
Run visitor type=7worker2
Worker2 run called. Object address [0x21bf048]
Stop visitor type=7worker1
Worker1 stop called. Object address [0x21bf038]
Stop visitor type=7worker2
Worker2 stop called. Object address [0x21bf048]