wondering
wondering

Reputation: 373

How to use a class member variable in a unary predicate?

Suppose I have the following code:

#include <vector>
#include <algorithm>
#include <cmath>

bool pred(float const &val)
{
    //return fabs(val) < epsilon;
}

class Foo
{
public:
    Foo(float eps) : epsilon(eps) { }

    int Bar(std::vector<float> vec)
    {
        return std::count_if(vec.begin(), vec.end(), pred);
    }
private:
    float epsilon;
}

I want to have the unary predicate pred() as a class method so that it can access the epsilon member variable. I've seen examples using the operator(), but if I got it right, the operator is supposed to compare the entire class instance. I only need to compare the given std::vector's elements in Bar(). Is it possible to create an unary predicate as a class member? If not, is there any other way to do it?

Upvotes: 3

Views: 3561

Answers (3)

Moby Disk
Moby Disk

Reputation: 3861

Your problem is that pred() needs two parameters but std::count_if wants a function that takes only one. @Praetorian's c++11 solution with lambdas is optimal. But without access to that, you should be able to use std::bind1st which does the operator () solution for you without you explicitly creating a class to do it.

#include <vector>
#include <algorithm>
#include <cmath>
#include <functional>

bool pred(float const &val, float epsilon)
{
    return fabs(val) < epsilon;
}

class Foo
{
public:
    Foo(float eps) : epsilon(eps) { }

    int Bar(std::vector<float> vec)
    {
        return std::count_if(vec.begin(), vec.end(), std::bind1st(std::less<float>(), epsilon));
    }
private:
    float epsilon;
};

Upvotes: 2

Daniel Kleinstein
Daniel Kleinstein

Reputation: 5502

Here's a C++98 solution:

class Pred{
    private:
        float eps;
    public:
        Pred(float eps) : eps(eps){
        }

        bool operator()(const float& val){
            return val < eps;
        }
};

And use it like this:

int Bar(std::vector<float> vec)
{
    Pred pred(epsilon);
    return std::count_if(vec.begin(), vec.end(), pred);
}

Note that this solution is general for whenever you need a predicate that requires additional data; write a class containing the additional data as class members, and overload the () operator. You can initialize an object of the class with the appropriate data and then use it as the predicate.

Upvotes: 2

rerun
rerun

Reputation: 25505

if you are using c++ 11 which you should be the easy way is a lambda

int Bar(std::vector<float> vec)
{
    return std::count_if(vec.begin(), vec.end(),[this](const float &f)
    {
        return fabs(val) < epsilon;
    });
}

Upvotes: 4

Related Questions