如何将 std::bind 与 compose2 一起使用?
How to use std::bind with compose2?
我想在 C++11 的 compose2
中使用 binary_function
和 std::bind
,而不使用 boost
库。
编辑: 或 labmdas.
假设我有以下定义:
bool GreaterThanFive(int x) { return x > 5; }
struct DivisibleByN : binary_function<int, int, bool> {
bool operator()(int x, int n) const { return x % n == 0; }
};
假设我想计算一个向量中大于 5 且可被 3 整除的元素。我可以轻松地将它们与以下内容组合:
int NumBothCriteria(std::vector<int> v) {
return std::count_if(v.begin(), v.end(),
__gnu_cxx::compose2(std::logical_and<bool>(),
std::bind2nd(DivisibleByN(), 3),
std::ref(GreaterThanFive)));
}
由于从 C++11 开始不推荐使用 bind2nd
,我想转到 std::bind
。我还没有弄明白为什么下面的不等价(并且不编译)。
int NumBothCriteria(std::vector<int> v) {
using namespace std::placeholders;
return std::count_if(v.begin(), v.end(),
__gnu_cxx::compose2(std::logical_and<bool>(),
std::bind(DivisibleByN(), _1, 3),
std::ref(GreaterThanFive)));
}
它给我以下编译错误:
no type named 'argument_type' in 'std::_Bind<DivisibleByN *(std::_Placeholder<1>, int)>`
operator()(const typename _Operation2::argument_type& __x) const
~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
我的直觉是 std::bind
没有做 std::bind2nd
做的事情,但我不确定如何恢复 argument_type
typedef。
My search came up with three questions. 第一个使用 bind2nd
,第二个使用 boost
,第三个用于 C++03。不幸的是 Effective STL 仍然使用 std::bind2nd
.
只是不要使用 bind
或 compose2
。稍后你会感谢自己的:
int NumBothCriteria(std::vector<int> v) {
return std::count_if(v.begin(), v.end(),
[](int i){ return i > 5 && i%3 == 0; });
}
您正在寻找的答案是您可以简单地使用 std::bind
代替您使用 __gnu_cxx::compose2
:
return std::count_if(v.begin(), v.end(),
std::bind(std::logical_and<bool>(),
std::bind(DivisibleByN(), _1, 3),
std::bind(GreaterThanFive, _1)));
但这比仅使用 lambda 更复杂,更难推理。
我想出了如何让它与 std::function
一起工作。
int NumBothCriteria2(std::vector<int> v) {
using std::placeholders::_1;
return std::count_if(v.begin(), v.end(),
__gnu_cxx::compose2(std::logical_and<bool>(),
std::function<int(int)>(std::bind(
DivisibleByN(), _1, 3)),
std::ref(GreaterThanFive)));
}
我想在 C++11 的 compose2
中使用 binary_function
和 std::bind
,而不使用 boost
库。
编辑: 或 labmdas.
假设我有以下定义:
bool GreaterThanFive(int x) { return x > 5; }
struct DivisibleByN : binary_function<int, int, bool> {
bool operator()(int x, int n) const { return x % n == 0; }
};
假设我想计算一个向量中大于 5 且可被 3 整除的元素。我可以轻松地将它们与以下内容组合:
int NumBothCriteria(std::vector<int> v) {
return std::count_if(v.begin(), v.end(),
__gnu_cxx::compose2(std::logical_and<bool>(),
std::bind2nd(DivisibleByN(), 3),
std::ref(GreaterThanFive)));
}
由于从 C++11 开始不推荐使用 bind2nd
,我想转到 std::bind
。我还没有弄明白为什么下面的不等价(并且不编译)。
int NumBothCriteria(std::vector<int> v) {
using namespace std::placeholders;
return std::count_if(v.begin(), v.end(),
__gnu_cxx::compose2(std::logical_and<bool>(),
std::bind(DivisibleByN(), _1, 3),
std::ref(GreaterThanFive)));
}
它给我以下编译错误:
no type named 'argument_type' in 'std::_Bind<DivisibleByN *(std::_Placeholder<1>, int)>`
operator()(const typename _Operation2::argument_type& __x) const
~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
我的直觉是 std::bind
没有做 std::bind2nd
做的事情,但我不确定如何恢复 argument_type
typedef。
My search came up with three questions. 第一个使用 bind2nd
,第二个使用 boost
,第三个用于 C++03。不幸的是 Effective STL 仍然使用 std::bind2nd
.
只是不要使用 bind
或 compose2
。稍后你会感谢自己的:
int NumBothCriteria(std::vector<int> v) {
return std::count_if(v.begin(), v.end(),
[](int i){ return i > 5 && i%3 == 0; });
}
您正在寻找的答案是您可以简单地使用 std::bind
代替您使用 __gnu_cxx::compose2
:
return std::count_if(v.begin(), v.end(),
std::bind(std::logical_and<bool>(),
std::bind(DivisibleByN(), _1, 3),
std::bind(GreaterThanFive, _1)));
但这比仅使用 lambda 更复杂,更难推理。
我想出了如何让它与 std::function
一起工作。
int NumBothCriteria2(std::vector<int> v) {
using std::placeholders::_1;
return std::count_if(v.begin(), v.end(),
__gnu_cxx::compose2(std::logical_and<bool>(),
std::function<int(int)>(std::bind(
DivisibleByN(), _1, 3)),
std::ref(GreaterThanFive)));
}