Search code examples
c++lambdabindnegate

How to negate boost::lambda:bind?


Let's say I have this type:

typedef boost::function<bool (Foo)> filter_function;

And a vector of those "filter functions":

std::vector<filter_function> filters;

If want to call all the filter functions, one by one, and only the the last call returned true.

Inspired by a previous question, I ended up writing:

bool Bar::filterFoo(Foo& foo)
{
  return (std::find_if(filters.begin(), filters.end(), boost::lambda::bind(boost::lambda::_1, foo)) == filters.end());
}

But this is wrong: the return value of the lambda should be negated.

I tried to use std::not1, std::not2 at different places but couldn't find any variation that doesn't end up in a (pretty verbose) compilation error.

What is the correct way to do this ?


Solution

  • You can simply negate the return value.

    bool Bar::filterFoo(Foo& foo)
    {
      return (std::find_if(filters.begin(), filters.end(), !boost::lambda::bind(boost::lambda::_1, foo)) == filters.end());
    }
    

    or you can use lambda from c++0X

    bool Bar::filterFoo(Foo& foo)
    {
        return (std::find_if(filters.begin(), filters.end(), [&foo](filter_function& f){
            return !f(foo);
        }
        ) == filters.end());
    }
    

    To show a complete example that works at least for VS2010.

    #include <iostream>
    #include <vector>
    #include <boost/function.hpp>
    #include <boost/lambda/lambda.hpp>
    #include <boost/bind.hpp>
    #include <boost/lambda/bind.hpp>
    
    using namespace std;
    
    struct Foo{};
    
    typedef boost::function<bool (Foo)> filter_function;
    std::vector<filter_function> filters;
    
    static int g_c = 0;
    bool MyFunc(Foo /*foo*/)
    {
        if(g_c > 1)
            return true;
        g_c++;
        return false;
    }
    bool filterFoo(Foo& foo)
    {
        return (std::find_if(filters.begin(), filters.end(), boost::lambda::bind(boost::lambda::_1, foo)) == filters.end());
    }
    bool negatefilterFoo(Foo& foo)
    {
        return (std::find_if(filters.begin(), filters.end(), !boost::lambda::bind(boost::lambda::_1, foo)) == filters.end());
    }
    
    int main() 
    {
        Foo f;
        filters.push_back(boost::bind(&MyFunc, _1));
        filters.push_back(boost::bind(&MyFunc, _1));
        filters.push_back(boost::bind(&MyFunc, _1));
        std::cout << filterFoo(f) << std::endl;
        std::cout << negatefilterFoo(f) << std::endl;
        return 0;
    }
    

    It returns 0 and 1 on my machine.