[bind] Generic loop with generic algorithm chicken and egg signature problem

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]'

Antonio Piccolboni wrote: [...]
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( std::accumulate< std::vector<int>::iterator, int >, _1, _2, 0 )
}
might work.

Thanks Peter, but it does not. Error message bind_test.cpp: In function 'int main()': bind_test.cpp:33: error: no matching function for call to 'bind(<unknown type>, const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >&, const boost::lambda::lambda_functor<boost::lambda::placeholder<2> >&, int)' This also dooms my theory of why this doesn't work since the explicit instantiation of the accumulate template should provide the necessary information. On 2/22/06, Peter Dimov <pdimov@mmltd.net> wrote:
Antonio Piccolboni wrote:
[...]
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( std::accumulate< std::vector<int>::iterator, int >, _1, _2, 0 )
}
might work. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Antonio Piccolboni wrote:
On 2/22/06, Peter Dimov <pdimov@mmltd.net> wrote:
bind( std::accumulate< std::vector<int>::iterator, int >, _1, _2, 0 )
might work.
Thanks Peter, but it does not. Error message
bind_test.cpp: In function 'int main()': bind_test.cpp:33: error: no matching function for call to 'bind(<unknown type>, const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >&, const boost::lambda::lambda_functor<boost::lambda::placeholder<2> >&, int)'
You are right, my g++ 3.4.4 also doesn't like it. MSVC 7.1 does, however, at least with boost::bind. There's always the workaround of using a cast or a temporary function pointer: typedef std::vector<int>::iterator It; int (*pf)( It, It, int ) = std::accumulate; bind( pf, _1, _2, 0 );
participants (2)
-
Antonio Piccolboni
-
Peter Dimov