在C ++中将多个参数绑定到成员函数

时间:2014-02-19 10:25:33

标签: c++ c++11 lambda bind

假设我有成员函数A的类int f() { return m_; },其中m_是数据成员。我有一个名为vector<A>的{​​{1}},我希望使用vecm_中找到最大vec值的对象。我可以用lambda做到这一点:

std::max_element

是否有一些auto cmp = [] (A& x, A& y) { return x.f() < y.f(); }; A& max_elem = *std::max_element(vec.begin(), vec.end(), cmp); (或某些此类)技巧可以让我在没有lambda的情况下完成它并且不从头开始定义我自己的比较器?请不要建议更好的方法来解决最大发现问题。这只是一个例子。一般的问题是如何包装一个带有多个参数的函数对象(例如,bind,我将在上面的例子中用作比较器),使得发送给它的参数经过一些其他功能(或成员功能)在到达之前。

2 个答案:

答案 0 :(得分:11)

是的,有:

using namespace std::placeholders;
A& max = *std::max_element(begin(vec), end(vec)
    , std::bind(
        &std::less<int>::operator()
        , std::less<int>()
        , std::bind(&A::f, _1)
        , std::bind(&A::f, _2)
    )
);

Live example

然而,如果我在代码审查中看到这一点,我会马上说“将丑陋变成一个lambda。”


感谢@ n.m.为了缩小代码可以缩短一点:

using namespace std::placeholders;
A& max = *std::max_element(begin(vec), end(vec)
    , std::bind(
        std::less<int>()
        , std::bind(&A::f, _1)
        , std::bind(&A::f, _2)
    )
);

Live example

但我仍然认为lambda更具可读性。请记住,您可以在调用max_element()时直接使用lambda(原始代码中不需要变量cmp)。

答案 1 :(得分:0)

您可以通过多种方式为算法提供谓词。您将在下面看到一些如何完成此操作的示例。以下是对std::max_element()的调用的摘要:

//here we're using an in-place lambda
A& max_elem = *std::max_element(vec.begin(), vec.end(), [](A& x, A&y){ return x.f() < y.f(); });
// here we're binding to a non-static member function
A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(&A::compare, A(0), std::placeholders::_1, std::placeholders::_2));
// here we're binding to a non-member function
A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(gcompare, std::placeholders::_1, std::placeholders::_2));
// here we're using the non-member function without using bind
A& max_elem = *std::max_element(vec.begin(), vec.end(), gcompare);

我们也可以使用std::function

这里是完整的测试源代码,您可以自己玩它:

class A
{
    int m_ = 0;
public:
    A(int max) : m_(max)
    {

    }
    A(const A& that)
    {
        m_ = that.m_;
    }
    A& operator=(const A& that)
    {
        m_ = that.m_;
    }
    int f() const
    {
        return m_;
    }
    bool compare(const A&x, const A&y) const
    {
        return x.m_ < y.m_;
    }
    static bool scompare(const A&x, const A&y)
    {
        return x.m_ < y.m_;
    }
};

static bool gcompare(const A&x, const A&y)
{
    return x.f() < y.f();
}

int main()
{
    std::vector<A> vec;
    vec.emplace_back(5);
    vec.emplace_back(7);
    vec.emplace_back(4);
    vec.emplace_back(9);
    vec.emplace_back(12);
    vec.emplace_back(1);


    A& max_elem = *std::max_element(vec.begin(), vec.end(), [](A& x, A&y){ return x.f() < y.f(); });
    A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(&A::compare, A(0), std::placeholders::_1, std::placeholders::_2));
    A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(gcompare, std::placeholders::_1, std::placeholders::_2));
    A& max_elem = *std::max_element(vec.begin(), vec.end(), gcompare);

}