views:

334

answers:

2

Hi,

I'm trying to create predicate for std::find_if by using boost::bind together with boost::contains (from boost/algoritm/string library). Following snippet shows two ways how I'm trying to accomplish this.

#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>

#include <iostream>
#include <string>

int main(int argc, char** argv) {
        std::string s1("hello mom");
        std::string s2("bye mom");

        boost::function<bool (std::string, std::string)> f = &boost::contains<std::string, std::string>;
        std::cout << s1 << " contains " << "hello, " << std::boolalpha << f(s1, "hello") << std::endl;
        std::cout << s2 << " contains " << "hello, " << std::boolalpha << f(s2, "hello") << std::endl;

        boost::function<bool (std::string)> contain_hello = boost::bind(boost::contains<std::string, std::string>, _1, std::string("hello"));
        std::cout << s1 << " contains " << "hello, " << std::boolalpha << contain_hello(s1) << std::endl;
        std::cout << s2 << " contains " << "hello, " << std::boolalpha << contain_hello(s2) << std::endl;
        return EXIT_SUCCESS;
}

When compiling this code with g++ 3.4.5 I'm getting following output.

error: conversion from `<unresolved overloaded function type>' to non-scalar type `boost::function<bool ()(std::string, std::string), std::allocator<void> >' requested
error: no matching function for call to `bind(<unresolved overloaded function type>, boost::arg<1>&, std::string)'

When I switch to boost::icontains which has only one overload everyting works fine. I know how to solve similar situation when there are multiple overloads of non-template function. Can someone help me write this correctly? Or should I write my own compare function?

A: 

That code looks fine (correct + compliant) to me, and it compiles using Visual Studio 2008 (with Microsoft language extensions disabled).

Try using a more up to date version of gcc.

Joe Gauterin
The problem is that in my production code I cannot use another compiler.
lollinus
In such a case, rely less on template magic: write a wrapper function which just uses the boost-code, and pass the wrapper function as argument to `find_if`.
gimpf
I understand perfectly that I can write my own functor/wrapper to do matching.I just wanted to learn what I'm missing in my reasoning while writing this code.Also I agree that code readability suffers when writing this as in accepted solution.
lollinus
+3  A: 

You need to write static_cast<bool(*)(const std::string&, const std::string&)>(&boost::contains<..>) to resolve the overload.

Yes, this is a royal pain with templates and overloading. Libs written with OOP and overloading in mind are difficult to use with templates and boost::bind.

We all wait for C++0x lambda expressions, which ought to resolve things better.

Marcus Lindblom
lollinus
Ok. Thanks. I've updated the answer with that. I've usually used this with member-function ptrs so my regular func-ptr syntax was a bit rusty, apparently. ;)
Marcus Lindblom