[range_ex] range adaptor and boost::lambda

Hi, Thanks for solving my previous find() problem. I found another problem of range_ex. The following code still works well with the old version of range_ex (Dec 2008), and cause a compile error with the newest version. code: #include <boost/range/adaptor/filtered.hpp> #include <boost/range/algorithm.hpp> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <boost/assign.hpp> #include <iostream> #include <vector> bool is_even(int x) { return x % 2 == 0; } int main() { using namespace boost::assign; using namespace boost::adaptors; using namespace boost::lambda; std::vector<int> input; input += 1,2,3,4,5,6,7,8,9; boost::copy( input | filtered(bind(is_even, _1)), std::ostream_iterator<int>(std::cout, ",") ); return 0; } compiler: msvc2008 error messages: d:\software\boost_1_37_0\boost\lambda\detail\lambda_traits.hpp(389) : warning C4180: qualifier applied to function type has no meaning; ignored d:\software\boost_1_37_0\boost\lambda\detail\lambda_traits.hpp(458) : see reference to class template instantiation 'boost::lambda::detail::bind_traits<T>' being compiled with [ T=bool (int) ] e:\zxg\boost\range_ex\range.cpp(20) : see reference to class template instantiation 'boost::lambda::detail::bind_tuple_mapper<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>' being compiled with [ T0=bool (int), T1=boost::lambda::placeholder1_type, T2=boost::tuples::null_type, T3=boost::tuples::null_type, T4=boost::tuples::null_type, T5=boost::tuples::null_type, T6=boost::tuples::null_type, T7=boost::tuples::null_type, T8=boost::tuples::null_type, T9=boost::tuples::null_type ] d:\software\boost_1_37_0\boost\tuple\detail\tuple_basic.hpp(383) : error C3853: '=': re-initializing a reference or assignment through a reference-to-function is illegal d:\software\boost_1_37_0\boost\tuple\detail\tuple_basic.hpp(382) : while compiling class template member function 'boost::tuples::cons<HT,TT> &boost::tuples::cons<HT,TT>::operator =(const boost::tuples::cons<HT,TT> &)' with [ HT=bool (__cdecl &)(int), TT=boost::tuples::cons<const boost::lambda::lambda_functor<boost::lambda::placeholder<1>>,boost::tuples::detail::map_tuple_to_cons<boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,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> ] d:\software\boost_1_37_0\boost\tuple\detail\tuple_basic.hpp(526) : see reference to class template instantiation 'boost::tuples::cons<HT,TT>' being compiled with [ HT=bool (__cdecl &)(int), TT=boost::tuples::cons<const boost::lambda::lambda_functor<boost::lambda::placeholder<1>>,boost::tuples::detail::map_tuple_to_cons<boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,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> ] d:\software\boost_1_37_0\boost\lambda\detail\lambda_functor_base.hpp(398) : see reference to class template instantiation 'boost::tuples::tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>' being compiled with [ T0=bool (__cdecl &)(int), T1=const boost::lambda::lambda_functor<boost::lambda::placeholder<1>>, T2=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type, T3=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type, T4=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type, T5=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type, T6=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type, T7=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type, T8=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type, T9=boost::lambda::detail::bind_traits<boost::tuples::null_type>::type ] d:\software\boost_1_37_0\boost\lambda\detail\lambda_functors.hpp(113) : see reference to class template instantiation 'boost::lambda::lambda_functor_base<Act,Args>' being compiled with [ Act=boost::lambda::action<2,boost::lambda::function_action<2,bool>>, Args=boost::tuples::tuple<bool (__cdecl &)(int),const boost::lambda::lambda_functor<boost::lambda::placeholder<1>>,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples: :null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type> ] e:\zxg\boost\range_ex\range.cpp(20) : see reference to class template instantiation 'boost::lambda::lambda_functor<T>' being compiled with [ T=boost::lambda::lambda_functor_base<boost::lambda::action<2,boost::lambda::function_action<2,bool>>,boost::tuples::tuple<bool (__cdecl &)(int),const boost::lambda::lambda_functor<boost::lambda::placeholder<1>>,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detai l::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type>> ] Thanks, Roger Zhou

Hi, On Fri, Apr 10, 2009 at 3:50 AM, 041021042 <041021042@fudan.edu.cn> wrote:
Hi,
I found another problem of range_ex. The following code still works well with the old version of range_ex (Dec 2008), and cause a compile error with the newest version.
The 'regression' was due to improved checking of the range concept constraints within the boost::copy algorithm. It appears that the filter_iterator assignment operator is invalid when used with the lambda expression you have chosen. Since the filter_iterator assignment is invalid it stands to reason that the range made from these iterators also did not have a valid assignment operator and hence the range library was correctly reporting that the result of the expression was not a valid model of the SinglePassRangeConcept. I suspect that the sample code provided was a stripped down example, but just in case it wasn't I would like to point out that: 1. is_even can be implemented more efficiently as bool is_even(int x) { return x & 1 == 0; } 2. The use of Boost.Lambda for the expression: boost::copy( input | filtered(bind(is_even, _1)), std::ostream_iterator<int>(std::cout, ",") ); Hence it can be replaced with: boost::copy( input | filtered(&is_even), std::ostream_iterator<int>(std::cout, ",") ); I have uploaded a new version to the Boost Vault that relaxes the SinglePassRangeConcept constraint to improve compatibility with Boost.Lambda. Thank you again for your report. I shall be making more tests for compatibility with Boost.Lambda and making improvements where appropriate. Best Wishes, Neil Groves
participants (2)
-
041021042
-
Neil Groves