0

Please advice, how I can solve the following problem – I want to have class member variable boost::variant type which has a type from defined mpl type sequence. After, in main, I want to call a method which calls method for every class method defined in sequence .. :) A little bit complicated but let me show:

struct worker1
{
   void init()
   {
      std::cout << "Worker1 init called" << std::endl;
   }
};

struct worker2
{
   void init()
   {
      std::cout << "Worker2 init called" << 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 ); // FAIL!!! :(( Doesn't work
      }
   };

   struct runinit
   {
      template<typename T> void operator()(T& x)
      {
         x.init();
      }
   };

   void init()
   {
      mpl::for_each<U>( runinit() );
   }

   void factory()
   {
      std::cout << "Factory start" << std::endl;
      mpl::for_each<U>( factoryrun() );
   }

   typedef typename boost::make_variant_over< U >::type types; // FAIL!!! Doesn't work because I need to have variant<worker1, worker2> but not variant<workers>
   static std::vector< boost::variant<types> > m_t;
};

template<typename K> std::vector< boost::variant<K> > process<K>::m_t;

int main() {
   process<workers> prs;
   // Here should be called init() for worker1 and worker2   
   prs.init();
   return 0;
}
manlio
  • 18,345
  • 14
  • 76
  • 126
LowCoder
  • 71
  • 3

2 Answers2

0

The problem is solved. Such a code is working

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 );
      }
   };

   struct runinit
   {
      template<typename T> void operator()(T& x)
      {
         x.init();
      }
   };

   void init()
   {
      mpl::for_each<U>( runinit() );
   }

   void factory()
   {
      std::cout << "Factory start" << std::endl;
      mpl::for_each<U>( factoryrun() );
   }

   typedef typename boost::make_variant_over< U >::type types;
   typedef std::vector< boost::variant<types> > Vector; // Make typedef to simplify
   static Vector m_t3;

};

template<typename U> typename process3<U>::Vector process3<U>::m_t3;

int main() {
   process3<workers> prs3;
   prs3.init();
 return 0;
}

Output:

Factory start
Factory entry
Type is = 7worker1
Factory entry
Type is = 7worker2
Worker1 init called
Worker2 init called
LowCoder
  • 71
  • 3
0

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]
LowCoder
  • 71
  • 3