The specific error you are encountering appears because boost lambdas are not CopyAssignable. Here's an easier way to get the same message:
auto f1 = _1 > 100; auto f2 = f1; f2 = f1;
If you provide CopyAssignable functor for filtered , boost.phoenix (which you should use anyway, boost.lambda is on the way to obsolescence in favor of phoenix), a handwritten structure or the old faithful std::bind2nd(std::greater<double>(), 100) , this line is compiled using clang ++:
bind2nd demo: http://liveworkspace.org/code/2xKZIf
phoenix demo: http://liveworkspace.org/code/18425g
It does not work with gcc due to some boost.concept check, which is probably a bug, but this is a moot point, because the result of filtered is boost::filtered_range , whose iterators do not have a member function .index() .
EDIT in response to a comment: comparing an iterator in filter_range with an iterator in the original vector will not work. However, since you used the vector and since it is still available, you can compare addresses, since neither indexed nor filtered make copies
#include <vector> #include <iostream> #include <cassert> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <boost/phoenix.hpp> using namespace boost::adaptors; using namespace boost::phoenix::placeholders; int main () { std::vector<double> x = {100, 150, 200, 110}; auto it = boost::max_element( x | indexed(0) | filtered(arg1 < 110) ); assert(&x[0] <= &*it && &*it < &x[0] + x.size()); std::cout << "Element " << *it << " is at index " << &*it - &x[0] << '\n'; }
demo http://liveworkspace.org/code/1zBIJ9
Or, for a more general solution, you can convert the vector to a vector of pairs (when boost receives a zip adapter, it can be carefully archived with counting_range) and carry the original index of the sequence along with the value through all the conversions.