std::bind2nd 的替代品
A replacement for std::bind2nd
我有一个 foo
,它是一个 std::vector<int>
。它表示一组范围的 "edge" 个值。
例如,如果 foo
为 {1, 3, 5, 7, 11},则范围为 1-3、3-5、5-7、7-11。对我来说很重要,这相当于 4 个时期。请注意,每个句点包括范围中的第一个数字,而不是最后一个数字。因此,在我的示例中,8 出现在第 3 个(从零开始)期间。 7也出现在第三期。 11 及以上不会出现在任何地方。 2出现在第0期。
给定一个 bar
,它是一个 int
,我使用
std::find_if(
foo.begin(),
foo.end(),
std::bind2nd(std::greater<int>(), bar)
) - foo().begin() - 1;
给我应该包含 bar
的句号。
我的问题:std::bind2nd
已弃用,所以我应该重构。使用更新函数的等效语句是什么? std::bind
显然没有 "drop in"。
在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
returns 一个函数对象,它在调用时带有一些参数。在对 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)
bind
版本为:
bind(std::greater<int>(), placeholders::_1, bar)
但我认为,更鼓励使用 lambda,如:
[bar](const int a){return bar < a;}
还鼓励使用重载函数 begin/end
而不是方法调用。所以它会像:
find_if(begin(foo), end(foo), [bar](const int a){return bar < a;})
使用 C++14 通用 lambda 直接从石器时代 (bind2nd
) 进入铁器时代,绕过青铜时代 (bind
) 怎么样?
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 谈谈。
我有一个 foo
,它是一个 std::vector<int>
。它表示一组范围的 "edge" 个值。
例如,如果 foo
为 {1, 3, 5, 7, 11},则范围为 1-3、3-5、5-7、7-11。对我来说很重要,这相当于 4 个时期。请注意,每个句点包括范围中的第一个数字,而不是最后一个数字。因此,在我的示例中,8 出现在第 3 个(从零开始)期间。 7也出现在第三期。 11 及以上不会出现在任何地方。 2出现在第0期。
给定一个 bar
,它是一个 int
,我使用
std::find_if(
foo.begin(),
foo.end(),
std::bind2nd(std::greater<int>(), bar)
) - foo().begin() - 1;
给我应该包含 bar
的句号。
我的问题:std::bind2nd
已弃用,所以我应该重构。使用更新函数的等效语句是什么? std::bind
显然没有 "drop in"。
在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
returns 一个函数对象,它在调用时带有一些参数。在对 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)
bind
版本为:
bind(std::greater<int>(), placeholders::_1, bar)
但我认为,更鼓励使用 lambda,如:
[bar](const int a){return bar < a;}
还鼓励使用重载函数 begin/end
而不是方法调用。所以它会像:
find_if(begin(foo), end(foo), [bar](const int a){return bar < a;})
使用 C++14 通用 lambda 直接从石器时代 (bind2nd
) 进入铁器时代,绕过青铜时代 (bind
) 怎么样?
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 谈谈。