Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using boost phoenix, how can I invoke a find_if call with starts_with?

I'm trying to find an element in a vector of structs. The code works when searching in a case-sensitive manner. When I try enhancing it to be case-insensitive, I run into two issues.

  1. Simply including boost/algorithm/string.hpp breaks the previously working VS2010 build. The error is "'boost::phoenix::bind' : ambiguous call to overloaded function". Builds OK in Xcode. Any way to disambiguate the bind?

  2. I guess I've got the syntax wrong in the second (commented out) find_if line, adding the istarts_with call. I get errors from the phoenix headers saying "error: no type named 'type'". Assuming issue #1 can be fixed, how should I correct this line?

Thanks!

Code:

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp> // This include breaks VS2010!
#include <boost/phoenix/bind.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/stl/algorithm.hpp>
using namespace boost::phoenix;
using boost::phoenix::arg_names::arg1;
using boost::istarts_with;
using std::string;
using std::cout;

// Some simple struct I'll build a vector out of
struct Person
{
    string FirstName;
    string LastName;
    Person(string const& f, string const& l) : FirstName(f), LastName(l) {}
};

int main()
{
    // Vector to search
    std::vector<Person> people;
    std::vector<Person>::iterator dude;

    // Test data
    people.push_back(Person("Fred", "Smith"));

    // Works!
    dude = std::find_if(people.begin(), people.end(), bind(&Person::FirstName, arg1) == "Fred");
    // Won't build - how can I do this case-insensitively?
    //dude = std::find_if(people.begin(), people.end(), istarts_with(bind(&Person::FirstName, arg1), "Fred"));

    if (dude != people.end())
        cout << dude->LastName;
    else
        cout << "Not found";
    return 0;
}
like image 489
Graham Perks Avatar asked Nov 04 '22 09:11

Graham Perks


1 Answers

You'd need two binds to make it work. First define:

int istw(string a, string b) { return istarts_with(a,b); }

and then use the following as the predicate for the find_if:

bind(&istw,bind(&Person::FirstName, arg1),"fred")

Two comments:

  1. Make sure you're using the right bind, namely, use boost::phoenix::bind.
  2. The definition of istw is probably unnecessary but I could not find the right way to replace it.
like image 143
MDman Avatar answered Nov 10 '22 12:11

MDman