替换std :: bind2nd

时间:2015-09-23 11:59:59

标签: c++ c++11 bind bind2nd

我的std::vector<int>foo。它代表着&#3​​4;边缘&#34;一组范围的值。

例如,如果bar是{1,3,5,7,11},那么范围是1-3,3-5,5-7,7-11。对我而言,这相当于4个时期。请注意,每个句点包括范围中的第一个数字,而不是最后一个数字。所以在我的例子中,8出现在第3个(从零开始)的时期。 7也出现在第3期。 11及以上并不会出现在任何地方。 2出现在第0期。

如果intstd::find_if( foo.begin(), foo.end(), std::bind2nd(std::greater<int>(), bar) ) - foo().begin() - 1; ,我会使用

bar

给我一​​个应该包含std::bind2nd的句号。

我的问题:std::bind已被弃用,所以我应该重构。使用更新函数的等效语句是什么? {{1}}没有&#34;&#34;辍学&#34;以明显的方式。

3 个答案:

答案 0 :(得分:12)

在C ++ 11中,您可以使用std::bind;它并不是显而易见的如何使用它:

#include <functional>
using namespace std::placeholders;
std::find_if(
    foo.begin(),
    foo.end(),
    // create a unary function object that invokes greater<int>::operator()
    // with the single parameter passed as the first argument and `bar` 
    // passed as the second argument
    std::bind(std::greater<int>(), _1, bar)
) - foo().begin() - 1;

关键是使用占位符参数,它在std::placeholders命名空间中声明。 std::bind返回一个函数对象,该对象在调用时会占用一些参数。调用std::bind内部使用的占位符显示调用结果对象时提供的参数如何映射到您要绑定的可调用参数列表。所以,例如:

auto op1 = std::bind(std::greater<int>(), _1, bar);
op1(5); // equivalent to std::greater<int>()(5, bar)

auto op2 = std::bind(std::greater<int>(), bar, _1);
op2(5); // equivalent to std::greater<int>()(bar, 5)

auto op3 = std::bind(std::greater<int>(), _2, _1);
op3(5, bar); // equivalent to std::greater<int>()(bar, 5)

auto op4 = std::bind(std::greater<int>(), _1, _2);
op4(5, bar); // equivalent to std::greater<int>()(5, bar)

答案 1 :(得分:11)

如何绕过青铜器时代(bind2nd)从石器时代(bind)直接进入具有C ++ 14通用lambda的铁器时代?

std::find_if(foo.begin(), foo.end(), [&](auto const& elem) { 
    return elem > bar; 
}); 

如果输入已排序

std::lower_bound(foo.begin(), foo.end(), bar); 

Lambda读取更容易,并且比std::bind表达式更容易内联。参见例如Lavevej's CppCon 2015说话。

答案 2 :(得分:5)

bind版本将是:

bind(std::greater<int>(), placeholders::_1, bar)

但我认为,更鼓励使用lambdas,如:

[bar](const int a){return bar < a;}

还鼓励使用重载函数begin/end而不是方法调用。所以它会像:

find_if(begin(foo), end(foo), [bar](const int a){return bar < a;})