Boost logo

Boost :

From: Hugo Duncan (hugoduncan_at_[hidden])
Date: 2003-10-23 14:18:41


David B. Held <dheld_at_[hidden]> wrote:

> Sounds close, but I can't look at your code because my
> newsreader doesn't have that thread, and the web-based
> ones try to interpret your attachment as HTML.

It's so short, I'll include it here :-)

Hugo

#include <boost/mpl/apply.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/aux_/unwrap.hpp>
#include <boost/utility/value_init.hpp>

namespace ieg
{
   namespace detail
   {

template <bool done = true>
struct switcher_impl
{
     template<
           typename Iterator
         , typename LastIterator
         , typename TransformFunc
         , typename F
         , typename Counter
>
     static void execute(
           Iterator*
         , LastIterator*
         , TransformFunc*
         , F
         , Counter*
         , std::size_t i
         )
     {
     }
};

template <>
struct switcher_impl<false>
{
     template<
           typename Iterator
         , typename LastIterator
         , typename TransformFunc
         , typename F
         , typename Counter
>
     static void execute(
           Iterator*
         , LastIterator*
         , TransformFunc*
         , F f
         , Counter*
         , std::size_t i
         )
     {
       if (i==Counter::value)
       {
         typedef typename Iterator::type item;
         typedef typename boost::mpl::apply1<TransformFunc,item>::type arg;

         // make sure not to invoke undefined behavior when we pass arg.
         boost::value_initialized<arg> x;
         boost::mpl::aux::unwrap(f, 0)(boost::get(x));
       }
       else
       {
         typedef typename Iterator::next iter;
         typedef typename Counter::next counter;
         switcher_impl<boost::is_same<iter,LastIterator>::value>::execute(
           (iter*)0, (LastIterator*)0, (TransformFunc*)0, f, (counter*)0,
i);
       }
     }
};

   }

   //! exectute a metafunction on an run-time selected element of type
sequence
   template <typename Sequence, typename TransformOp, typename F>
   void switcher(F f, std::size_t i, Sequence* = 0, TransformOp* = 0)
   {
     typedef typename boost::mpl::begin<Sequence>::type first;
     typedef typename boost::mpl::end<Sequence>::type last;
     typedef typename boost::mpl::lambda<TransformOp>::type transform_op;
     typedef typename boost::mpl::integral_c<std::size_t,0>::type counter;

     detail::switcher_impl< boost::is_same<first,last>::value >::execute(
         (first*)0, (last*)0, (transform_op*)0, f, (counter*)0, i);
   }

   template <typename Sequence, typename F>
   void switcher(F f, std::size_t i, Sequence* = 0)
   {
     switcher<Sequence, boost::mpl::make_identity<> >(f,i);
   }

}// namespace

#include <cstdlib>
#include <typeinfo>
#include <iostream>
#include <boost/mpl/vector.hpp>

struct myfn
{
   template < typename U > void operator()(const boost::mpl::identity<U>&)
   {
     std::cout << typeid(U).name() << std::endl;
   }
};

int main()
{
   typedef boost::mpl::vector<double, float> my_typelist;
   for (int i=0; i<2; ++i)
     ieg::switcher<my_typelist>(myfn(),i);

   ieg::switcher<my_typelist>(myfn(),1);
   ieg::switcher<my_typelist>(myfn(),2);//< silent, no error
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk