Question

I'm trying to use boost::lambda::bind() to define a predicate that I pass to the find_if algorithm in Boost.Range. Specifically, I want to search a vector of structures to find the first entry where a particular member has a specified value. My example is as follows:

#include <boost/lambda/bind.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <vector>

using namespace std;
using namespace boost;
using namespace boost::lambda;

struct foo
{
    string s;
    int x;
};

int main()
{
    // create list and add a couple entries
    vector<foo> fooList;
    foo f1 = {"abc", 1};
    foo f2 = {"def", 2};
    fooList.push_back(f1);
    fooList.push_back(f2);
    // search for a value with the desired member
    //     fails with a compile error!
    range_iterator<vector<foo> > it = find_if(fooList, boost::lambda::bind(&foo::s, _1) == string("abc"));
    return 0;
}

When I try to compile this (under gcc 4.7.2), I get the typical spew of template instantiation errors, indicating that there was no operator== found that is compatible with the type returned by bind() and a const char []. I've tried this with other types also, such as int, with the same result.

I must be missing some small detail of bind() usage, but I can't see it; it seems like this sort of thing should work based upon the documentation. Am I wrong there?

Edit: Here is the first part of the compiler output:

test.cc:24:92: error: no match for ‘operator==’ in ‘boost::lambda::bind(const Arg1&, const Arg2&) [with Arg1 = std::basic_string<char> foo::*; Arg2 = boost::lambda::lambda_functor<boost::lambda::placeholder<1> >; typename boost::lambda::detail::bind_tuple_mapper<const Arg1, const Arg2>::type = boost::tuples::tuple<std::basic_string<char> foo::* const, const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >, 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::lambda::{anonymous}::_1)) == "abc"’
Was it helpful?

Solution

Turns out that I wasn't including the required headers. It appears that <boost/lambda/bind.hpp> only brings in bind functionality, and the operator overloads for the resulting type are not included. If I add #include <boost/lambda/lambda.hpp> to the above, then it resolves the compiler error that I referenced. The final revised code (fixing another error in the type of the return value from find_if()) is as follows:

#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <string>
#include <vector>

using namespace std;
using namespace boost;
using namespace boost::lambda;

struct foo
{
    string s;
    int x;
};

int main()
{
    // create list and add a couple entries
    vector<foo> fooList;
    foo f1 = {"abc", 1};
    foo f2 = {"def", 2};
    fooList.push_back(f1);
    fooList.push_back(f2);
    // search for a value with the desired member
    typename range_iterator<vector<foo> >::type it = find_if(fooList, bind(&foo::s, _1) == "abc");
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top