替换std :: bind2nd

P45*_*ent 11 c++ bind bind2nd c++11

我有一个foostd::vector<int>.它表示一组范围的"边缘"值.

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

鉴于bar哪个是int,我使用

std::find_if(
    foo.begin(),
    foo.end(),
    std::bind2nd(std::greater<int>(), bar)
) - foo().begin() - 1;
Run Code Online (Sandbox Code Playgroud)

给我应该包含的时期bar.

我的问题:std::bind2nd已被弃用,所以我应该重构.使用更新函数的等效语句是什么?std::bind不会以明显的方式"堕入".

Jas*_*n R 13

在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;
Run Code Online (Sandbox Code Playgroud)

关键是使用占位符参数,它在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)
Run Code Online (Sandbox Code Playgroud)


Tem*_*Rex 13

怎么样从石器时代(bind2nd)走向铁器时代的C++ 14通用lambda,绕过青铜器时代(bind)?

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

如果输入已排序

std::lower_bound(foo.begin(), foo.end(), bar); 
Run Code Online (Sandbox Code Playgroud)

Lambda读取更容易,并且比std::bind表达更容易内联.参见Lavevej的CppCon 2015谈话.

  • 我同意这可能是最容易阅读的解决方案,但问题的标签仅包含 C++11。 (2认同)
  • @JasonR我的理念是展示我将如何编码,除非他们声称他们确实不能使用C ++ 14,即使如此,如果节省的钱足够多,我也将展示它:)问答并非仅用于OP,但适用于广大公众。但是我赞成你的“ bind”答案:) (2认同)

beh*_*uri 5

bind 版本将是:

bind(std::greater<int>(), placeholders::_1, bar)
Run Code Online (Sandbox Code Playgroud)

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

[bar](const int a){return bar < a;}
Run Code Online (Sandbox Code Playgroud)

还鼓励使用重载函数begin/end而不是方法调用.所以它会是这样的:

find_if(begin(foo), end(foo), [bar](const int a){return bar < a;})
Run Code Online (Sandbox Code Playgroud)