假设我有成员函数A
的类int f() { return m_; }
,其中m_
是数据成员。我有一个名为vector<A>
的{{1}},我希望使用vec
在m_
中找到最大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
,我将在上面的例子中用作比较器),使得发送给它的参数经过一些其他功能(或成员功能)在到达之前。
答案 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)
)
);
然而,如果我在代码审查中看到这一点,我会马上说“将丑陋变成一个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)
)
);
但我仍然认为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);
}