C++03 根据成员函数值查找元素
C++03 Finding an element based in a member function value
我试图在基于成员函数的 std::vector 中找到一个元素,但不幸的是我无法访问完全符合 C++11 的编译器。
我知道我可以使用仿函数来解决这个问题,但我想知道是否有 "functional" 方法来实现相同的结果。
下面是描述我的问题的片段:
#include <iostream>
#include <string>
#include <functional>
#include <algorithm>
#include <vector>
struct Class {
int type_;
Class(int type): type_(type) {
}
int GetType() {
return type_;
}
};
struct Functor {
Functor(int t): t_(t) {
}
bool operator()(Class c) {
return c.GetType() == t_;
}
int t_;
};
int main() {
// It also works
std::vector<Class> v2 { Class(1), Class(2), Class(3), Class(4), Class(5) };
auto it2 = std::find_if(v2.begin(), v2.end(), Functor(4));
std::cout << (it2 != v2.end() ? "Found!" : "Not found!") << std::endl;
// It would solve, but I can't use due to compiler limitations :(
it2 = std::find_if(v2.begin(), v2.end(), [](auto& v) { return v.GetType() == 4; });
std::cout << (it2 != v2.end() ? "Found!" : "Not found!") << std::endl;
// Is there any "functional based" solution to this, using std::mem_fun, std::bind1st, etc.?
// it2 = std::find_if(v2.begin(), v2.end(), ???);
return 0;
}
如果我的 std::vector 是由非复杂类型构成的,我会这样做:
std::vector<int> v1 { 1, 2, 3, 4, 5 };
auto it1 = std::find_if(v1.begin(), v1.end(), std::bind1st(std::equal_to<int>(), 4));
std::cout << (it1 != v1.end() ? "Found!" : "Not found!") << std::endl;
写个类似上面的代码有什么解决办法吗?
编辑:
我正在使用 GCC 4.4.1
编辑2:
根据一些评论和@scohe001 的回复,我将解决重载全局 == 运算符的问题。
但我的好奇心还没有得到满足:)
有没有办法使用 <funtional>
的 std 工具集来实现我的目标?
编辑3:
只是澄清一下:阅读回复和评论后,我知道可以解决我在使用 operator==(int)
重载之前发布的简单示例,并且还知道我可以使用 function object (functor)
来完成 lambda 表达式的相同工作。但是,我真正的问题是:仅使用 <functional>
中可用的工具集(std::mem_fun、std::bind1st、std::equal_to 等),我可以 "mimic" lambda/functor 的行为?如果是这样,我如何 "chain" 函数调用来做到这一点?
编辑4:
显然,仅使用 <functional>
的现有工具集无法解决我的问题,所以我接受 @Caleth
的回应,一旦它是更接近我的正在尝试做。
听起来你不能修改结构定义本身,所以在全局范围内为 operator==
创建一个重载:
bool operator==(const Class &lhs, const Class &rhs) {
return lhs.type_ == rhs.type_;
}
然后你可以使用常规的旧 find
:
std::find(v2.begin(), v2.end(), Class(4));
您必须自己编写 bind_both
适配器
it2 = std::find_if(v2.begin(), v2.end(), bind_both(std::equal_to<int>(), std::mem_fn_ref(&Class::getType), 4));
而且它会带来可能性的组合爆炸
template <typename Binary, typename Left, typename Arg>
class bind_left_t : public std::unary_function<Arg, typename Binary::result_type> {
Binary b;
Left l;
typename Binary::second_argument_type r;
public:
bind_left_t(Binary b, Left l, typename Binary::second_argument_type r) : b(b), l(l), r(r) {}
typename Binary::result_type operator()( Arg & arg) const { return b(l(arg), r); }
typename Binary::result_type operator()(const Arg & arg) const { return b(l(arg), r); }
};
template <typename Binary, typename Right, typename Arg>
class bind_right_t : public std::unary_function<Arg, typename Binary::result_type> {
Binary b;
typename Binary::first_argument_type l;
Right r;
public:
bind_right_t(Binary b, typename Binary::first_argument_type l, Right r) : b(b), l(l), r(r) {}
typename Binary::result_type operator()( Arg & arg) const { return b(l, r(arg)); }
typename Binary::result_type operator()(const Arg & arg) const { return b(l, r(arg)); }
};
template <typename Binary, typename Left, typename Right, typename Arg1, typename Arg2>
class bind_both_t : public std::binary_function<Arg1, Arg2, typename Binary::result_type> {
Binary b;
Left l;
Right r;
public:
bind_both_t (Binary b, Left l, Right r) : b(b), l(l), r(r) {}
typename Binary::result_type operator()( Arg1 & arg1, Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
typename Binary::result_type operator()(const Arg1 & arg1, Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
typename Binary::result_type operator()( Arg1 & arg1, const Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
typename Binary::result_type operator()(const Arg1 & arg1, const Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
};
额外的模板参数(Arg
、Arg1
和 Arg2
)在调用 bind_both
时消除了三种形式之间的歧义
template <typename Binary, typename Left>
bind_left_t<Binary, Left, typename Left::argument_type> bind_both(Binary b, Left l, typename Binary::second_argument_type r)
{
return bind_left_t<Binary, Left, typename Left::argument_type>(b, l, r);
}
template <typename Binary, typename Right>
bind_right_t<Binary, Right, typename Right::argument_type> bind_both(Binary b, typename Binary::first_argument_type l, Right r)
{
return bind_right_t<Binary, Right, typename Right::argument_type>(b, l, r);
}
template <typename Binary, typename Left, typename Right>
bind_both_t<Binary, Left, Right, typename Left::argument_type, typename Right::argument_type> bind_both(Binary b, Left l, Right r)
{
return bind_both_t<Binary, Left, Right, typename Left::argument_type, typename Right::argument_type>(b, l, r);
}
我试图在基于成员函数的 std::vector 中找到一个元素,但不幸的是我无法访问完全符合 C++11 的编译器。
我知道我可以使用仿函数来解决这个问题,但我想知道是否有 "functional" 方法来实现相同的结果。
下面是描述我的问题的片段:
#include <iostream>
#include <string>
#include <functional>
#include <algorithm>
#include <vector>
struct Class {
int type_;
Class(int type): type_(type) {
}
int GetType() {
return type_;
}
};
struct Functor {
Functor(int t): t_(t) {
}
bool operator()(Class c) {
return c.GetType() == t_;
}
int t_;
};
int main() {
// It also works
std::vector<Class> v2 { Class(1), Class(2), Class(3), Class(4), Class(5) };
auto it2 = std::find_if(v2.begin(), v2.end(), Functor(4));
std::cout << (it2 != v2.end() ? "Found!" : "Not found!") << std::endl;
// It would solve, but I can't use due to compiler limitations :(
it2 = std::find_if(v2.begin(), v2.end(), [](auto& v) { return v.GetType() == 4; });
std::cout << (it2 != v2.end() ? "Found!" : "Not found!") << std::endl;
// Is there any "functional based" solution to this, using std::mem_fun, std::bind1st, etc.?
// it2 = std::find_if(v2.begin(), v2.end(), ???);
return 0;
}
如果我的 std::vector 是由非复杂类型构成的,我会这样做:
std::vector<int> v1 { 1, 2, 3, 4, 5 };
auto it1 = std::find_if(v1.begin(), v1.end(), std::bind1st(std::equal_to<int>(), 4));
std::cout << (it1 != v1.end() ? "Found!" : "Not found!") << std::endl;
写个类似上面的代码有什么解决办法吗?
编辑:
我正在使用 GCC 4.4.1
编辑2:
根据一些评论和@scohe001 的回复,我将解决重载全局 == 运算符的问题。
但我的好奇心还没有得到满足:)
有没有办法使用 <funtional>
的 std 工具集来实现我的目标?
编辑3:
只是澄清一下:阅读回复和评论后,我知道可以解决我在使用 operator==(int)
重载之前发布的简单示例,并且还知道我可以使用 function object (functor)
来完成 lambda 表达式的相同工作。但是,我真正的问题是:仅使用 <functional>
中可用的工具集(std::mem_fun、std::bind1st、std::equal_to 等),我可以 "mimic" lambda/functor 的行为?如果是这样,我如何 "chain" 函数调用来做到这一点?
编辑4:
显然,仅使用 <functional>
的现有工具集无法解决我的问题,所以我接受 @Caleth
的回应,一旦它是更接近我的正在尝试做。
听起来你不能修改结构定义本身,所以在全局范围内为 operator==
创建一个重载:
bool operator==(const Class &lhs, const Class &rhs) {
return lhs.type_ == rhs.type_;
}
然后你可以使用常规的旧 find
:
std::find(v2.begin(), v2.end(), Class(4));
您必须自己编写 bind_both
适配器
it2 = std::find_if(v2.begin(), v2.end(), bind_both(std::equal_to<int>(), std::mem_fn_ref(&Class::getType), 4));
而且它会带来可能性的组合爆炸
template <typename Binary, typename Left, typename Arg>
class bind_left_t : public std::unary_function<Arg, typename Binary::result_type> {
Binary b;
Left l;
typename Binary::second_argument_type r;
public:
bind_left_t(Binary b, Left l, typename Binary::second_argument_type r) : b(b), l(l), r(r) {}
typename Binary::result_type operator()( Arg & arg) const { return b(l(arg), r); }
typename Binary::result_type operator()(const Arg & arg) const { return b(l(arg), r); }
};
template <typename Binary, typename Right, typename Arg>
class bind_right_t : public std::unary_function<Arg, typename Binary::result_type> {
Binary b;
typename Binary::first_argument_type l;
Right r;
public:
bind_right_t(Binary b, typename Binary::first_argument_type l, Right r) : b(b), l(l), r(r) {}
typename Binary::result_type operator()( Arg & arg) const { return b(l, r(arg)); }
typename Binary::result_type operator()(const Arg & arg) const { return b(l, r(arg)); }
};
template <typename Binary, typename Left, typename Right, typename Arg1, typename Arg2>
class bind_both_t : public std::binary_function<Arg1, Arg2, typename Binary::result_type> {
Binary b;
Left l;
Right r;
public:
bind_both_t (Binary b, Left l, Right r) : b(b), l(l), r(r) {}
typename Binary::result_type operator()( Arg1 & arg1, Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
typename Binary::result_type operator()(const Arg1 & arg1, Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
typename Binary::result_type operator()( Arg1 & arg1, const Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
typename Binary::result_type operator()(const Arg1 & arg1, const Arg2 & arg2) const { return b(l(arg1), r(arg2)); }
};
额外的模板参数(Arg
、Arg1
和 Arg2
)在调用 bind_both
template <typename Binary, typename Left>
bind_left_t<Binary, Left, typename Left::argument_type> bind_both(Binary b, Left l, typename Binary::second_argument_type r)
{
return bind_left_t<Binary, Left, typename Left::argument_type>(b, l, r);
}
template <typename Binary, typename Right>
bind_right_t<Binary, Right, typename Right::argument_type> bind_both(Binary b, typename Binary::first_argument_type l, Right r)
{
return bind_right_t<Binary, Right, typename Right::argument_type>(b, l, r);
}
template <typename Binary, typename Left, typename Right>
bind_both_t<Binary, Left, Right, typename Left::argument_type, typename Right::argument_type> bind_both(Binary b, Left l, Right r)
{
return bind_both_t<Binary, Left, Right, typename Left::argument_type, typename Right::argument_type>(b, l, r);
}