Boost logo

Boost Users :

Subject: Re: [Boost-users] generate an n-deep runtime for loop
From: Hicham Mouline (hicham_at_[hidden])
Date: 2010-01-24 04:00:54


----- Original Message -----
From: "joel falcou" <joel.falcou_at_[hidden]>
To: <boost-users_at_[hidden]>
Sent: Friday, January 22, 2010 1:41 AM
Subject: Re: [Boost-users] generate an n-deep runtime for loop
> Hicham Mouline wrote:

Please refer to the first post of this thread for the initial question.

I believe the compiler got stuck in an infinite loop of template
instantiations from my code. It hasn't stopped printing instantiation
backtraces when I interrupted it and never reached printing the actuall
error :-)

The code is
///@param params_seq fusion::vector< variant<>, variant<>, ...., variant<>
>
///@param body a callable that takes a parameters_t const-ref as an argument
///
template <typename parameters_t,
          typename params_1_n_seq_t,
          typename inner_body_t,
          typename N = typename
boost::fusion::result_of::size<parameters_t>::type >
struct for_recursive {
  void operator()(parameters_t& params, const params_1_n_seq_t& params_seq,
const inner_body_t& body) const
  {
    for_iterate<N>( boost::fusion::front(params_seq), params, params_seq,
body );
  }
};

/// Partial specialization for case 0
template <typename parameters_t,
          typename params_1_n_seq_t,
          typename inner_body_t>
struct for_recursive< parameters_t, params_1_n_seq_t, inner_body_t,
boost::mpl::int_<0> > {
  void operator()(parameters_t& params, const params_1_n_seq_t& params_seq,
const inner_body_t& body) const
  {
    body(params);
  }
};

Is the second half a partial specialization of the primary template, for the
case N = int_<0> ?

for_iterate is a template function that applies a visitor on the front
variant of the sequence.
The visitor then calls for_recursive<>::operator() back with the fusion
sequence with the front popped, and N decremented by 1, mpl::minus<N,
int_<1>>...

template <typename N,
          typename T,
          typename parameters_t,
          typename params_1_n_seq_t,
          typename inner_body_t>
void for_iterate( const boost::variant< std::vector<T>, range_incr<T>,
range<T>, T >& v,
    parameters_t& params, const params_1_n_seq_t& params_seq, const
inner_body_t& body )
{
  boost::apply_visitor(
for_iterate_visitor<T,parameters_t,params_1_n_seq_t,inner_body_t,N>(params,
params_seq, body), v );
}

This visitor is below:

///
/// visitor for the "for iterator"
///
template <typename T,
          typename parameters_t,
          typename params_1_n_seq_t,
          typename inner_body_t,
   typename N>
class for_iterate_visitor: public boost::static_visitor<> {
public:
  for_iterate_visitor(parameters_t& params, const params_1_n_seq_t&
params_seq, const inner_body_t& body)
    : params_(params), params_seq_(params_seq), params_reduced_seq_(
boost::fusion::pop_front(params_seq) ), body_(body)
  {}

private:
  typedef typename boost::fusion::result_of::size<parameters_t>::type
size_of_parameters_t;
  typedef typename boost::mpl::minus< size_of_parameters_t , N >::type
Index;
  typedef typename boost::mpl::minus<N, boost::mpl::int_<1> >::type Nminus1;
  typedef typename boost::fusion::result_of::pop_front<const
params_1_n_seq_t>::type params_1_n_reduced_seq_t;

public:
  void operator()( const std::vector<T>& v ) const
  {
    for (size_t index=0; index<v.size(); ++index) {
      boost::fusion::at<Index, parameters_t>(params_) = v[index];
      for_recursive<parameters_t, params_1_n_reduced_seq_t, inner_body_t,
Nminus1>()( params_, params_reduced_seq_, body_ );
    }
  }
  void operator()( const range_incr<T>& r) const
  {
    for (T param=r.min; param<=r.max; param+=r.incr) {
      boost::fusion::at<Index, parameters_t>(params_) = param;
      for_recursive<parameters_t, params_1_n_reduced_seq_t, inner_body_t,
Nminus1>()( params_, params_reduced_seq_, body_ );
    }
  }
  void operator()( const range<T>& r ) const
  {
    for (T param=r.min; param<=r.max; ++param) {
      boost::fusion::at<Index, parameters_t>(params_) = param;
      for_recursive<parameters_t, params_1_n_reduced_seq_t, inner_body_t,
Nminus1>()( params_, params_reduced_seq_, body_ );
    }
  }
  void operator()( T param ) const
  {
    boost::fusion::at<Index, parameters_t>(params_) = param;
    for_recursive<parameters_t, params_1_n_reduced_seq_t, inner_body_t,
Nminus1>()( params_, params_reduced_seq_, body_ );
  }
private:
  parameters_t& params_;
  const params_1_n_seq_t& params_seq_;
  const params_1_n_reduced_seq_t& params_reduced_seq_;
  const inner_body_t& body_;
};

The full code doesn't compile, the entry point is

for_recursive<params1_t, params1_1_n_seq_t, for_print_it>()( p, p2,
for_print_it() );

struct for_print_it {
   void operator()(const params1& p) const
  {
    std::cout<< p.field1<<std::endl;
  }
};

regards,


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net