Boost logo

Boost Users :

From: Antonio Piccolboni (piccolbo_at_[hidden])
Date: 2006-02-22 14:22:22


 I have a vector of vectors or some nested data structure of that sort. I
want to loop over the outer structure and summarize the inner structure,
like taking averages of all the vectors or what not. Once I saw that in the
code three times I thought it was time to abstract it out. So the plan was
to have a generic loop function that takes a functor type for the action to
perform inside the loop. So far so good. In many instances that action is a
standard algorithm or composition thereof, so why not use functors like
those returned by bind(accumulate, _1, _2, 0) instead of writing little
polluting classes like BinFunc below? But the compiler is at a loss guessing
the types, and it looks to me like it is for a good reason, because to
instantiate the accumulate template it has to know the precise signature of
my loop function and the converse too. Can the lambda experts shed light on
this? It seems a quite natural use case. Thanks

Antonio

PS: in an ideal world the following example can be done combining transform
call_begin and call_end, but that an whole different story

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <vector>
#include <numeric>
#include <functional>

using namespace boost::lambda;

template<class Func, class NestedIt, class It>
void loop_func(NestedIt start, NestedIt stop, It dest, Func f) {
  for(;start < stop; start++, dest++) {
    *dest = f(start->begin(), start->end());
  }
}

class BinFunc:
  public std::binary_function<std::vector<int>::iterator,
             std::vector<int>::iterator, int> {
public:
  int operator()
    (std::vector<int>::iterator b,
     std::vector<int>::iterator e) {
    return accumulate(b,e,0);
  }
};
int main() {
  std::vector<int> d;
  std::vector<std::vector<int> > s;
  loop_func(s.begin(), s.end (), d.begin(),
        BinFunc()); //flies with gcc
  loop_func(s.begin(), s.end(), d.begin(),
          bind<int>(std::accumulate, _1, _2, 0.0)); //does not
}

bind_test.cpp: In function 'int main()':
bind_test.cpp:32: error: invalid initialization of reference of type 'const
int&' from expression of type '<unknown type>'
/usr/include/boost/lambda/detail/bind_functions.hpp:532: error: in passing
argument 1 of 'const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::action<4,
boost::lambda::function_action<4, boost::lambda::detail::unspecified> >,
typename boost::lambda::detail::bind_tuple_mapper<const Arg1, const Arg2,
const Arg3, const Arg4, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type>::type> >
boost::lambda::bind(const Arg1&, const Arg2&, const Arg3&, const Arg4&)
[with Arg1 = int, Arg2 =
boost::lambda::lambda_functor<boost::lambda::placeholder<1> >, Arg3 =
boost::lambda::lambda_functor<boost::lambda::placeholder<2> >, Arg4 =
double]'



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