为什么没有mem_data?

HaoGeGe 2003-01-08 05:06:27
我们知道有一个mem_fun的函数适配器.但是为什么没有一个mem_data的数据适配器呢?
比如,有一个学生信息的结构体,把很多学生信息放在一个容器中,当我想查出学生姓名
为"某某",我如果想用find_if算法我就不得不要写一个函数对象,把学生姓名数据成员
和"某某"去比较.("某某"在函数对象的构造函数中传入).可是如果我想查出学生的年龄
为"某某"时我还得又写一个类似的函数对象.
如果有一个mem_data的数据适配器的话那我就可以利用equal_to等现成的函数对象了.
但是为什么没有mem_data?
...全文
69 18 打赏 收藏 举报
写回复
18 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
zhaohangcom 2003-03-21
``经典
  • 打赏
  • 举报
回复
HaoGeGe 2003-01-16
输出结果:
sort by field1
4
3
1
sort by field2
Z
C
A
sort by field3
test3
test2
test1
Press any key to continue
  • 打赏
  • 举报
回复
HaoGeGe 2003-01-16
呵呵,可以暂时结束这个问题.
我做了一个完整的例子程序.演示了查询和排序.
谢谢, 百宝箱

template<class R, class T>
class mem_data_ref_t : public std::unary_function<T,R>{
public:
typedef R T::* pointer_type;
explicit mem_data_ref_t(pointer_type p)
: ptr_(p) {}
R operator()(const T& r) const
{return (r.*ptr_); }
private:
pointer_type ptr_;
};

template<class R, class T> inline
mem_data_ref_t<R, T> mem_data_ref(R T::* p)
{return (mem_data_ref_t<R,T>(p)); }

//-----------------------------------------------------------//

struct foo{
int field1;
char field2;
string field3;
};



template <class Operation1, class Operation2>
class unary_compose_binary_aug : public binary_function<Operation2::argument_type,
Operation2::argument_type,
Operation1::result_type> {
protected:
Operation1 op1;
Operation2 op2;
public:
unary_compose_binary_aug(const Operation1& x, const Operation2& y) : op1(x), op2(y) { }
result_type operator()(const first_argument_type& x, const second_argument_type& y) const {
return op1(op2(x), op2(y));
}
};

template <class Operation1, class Operation2>
unary_compose_binary_aug<Operation1, Operation2>
compose1_2a(const Operation1& op1, const Operation2& op2) {
return unary_compose_binary_aug<Operation1, Operation2>(op1, op2);
}


int main()
{
const int value1=3;
const string value2="test2";
foo f1, f2, f3;

f1.field1=4;
f2.field1=1;
f3.field1=3;

f1.field2=65;
f2.field2=67;
f3.field2=90;

f1.field3="test3";
f2.field3="test2";
f3.field3="test1";

typedef std::vector<foo> V;
V v;
v.push_back(f1);
v.push_back(f2);
v.push_back(f3);

//find field1 by value1
V::iterator result = std::find_if(v.begin(),v.end(),
compose1(
bind2nd(std::equal_to<int>(),value1),
mem_data_ref(&foo::field1)));

assert((*result).field1==value1);

//find field3 by value2
result = std::find_if(v.begin(),v.end(),
compose1(
bind2nd(std::equal_to<string>(),value2),
mem_data_ref(&foo::field3)));

assert((*result).field3==value2);

//compose to f(g(x),g(x))

//sort by field1
std::sort(v.begin(),v.end(),compose1_2a(greater<int>(),mem_data_ref(&foo::field1)));
cout << "sort by field1" << endl;
for(result = v.begin(); result < v.end(); ++result)
cout << mem_data_ref(&foo::field1)(*result)<< endl;

//sort by field2
std::sort(v.begin(),v.end(),compose1_2a(greater<char>(),mem_data_ref(&foo::field2)));
cout << "sort by field2" << endl;
for(result = v.begin(); result < v.end(); ++result)
cout << mem_data_ref(&foo::field2)(*result)<< endl;


//sort by field3
std::sort(v.begin(),v.end(),compose1_2a(greater<string>(),mem_data_ref(&foo::field3)));
cout << "sort by field3" << endl;
for(result = v.begin(); result < v.end(); ++result)
cout << mem_data_ref(&foo::field3)(*result)<< endl;


return 0;
}
  • 打赏
  • 举报
回复
anrxhzh 2003-01-10
谈不上高手,毕竟STL的源码就在那里,学就行了。可以实现一个mem_data_ref的,如下:

//-----------------------------------------------------------
#include <functional>

template<class R, class T>
class mem_data_ref_t : public std::unary_function<T,R>{
public:
typedef R T::* pointer_type;
explicit mem_data_ref_t(pointer_type p)
: ptr_(p) {}
R operator()(const T& r) const
{return (r.*ptr_); }
private:
pointer_type ptr_;
};

template<class R, class T> inline
mem_data_ref_t<R, T> mem_data_ref(R T::* p)
{return (mem_data_ref_t<R,T>(p)); }

//-----------------------------------------------------------//

#include <vector>
#include <algorithm>
#include <cassert>

struct foo{
int field;
};

int main()
{
const int value=1;
foo f;
f.field=value;

typedef std::vector<foo> V;
V v;
v.push_back(f);

V::iterator result = std::find_if(v.begin(),v.end(),
std::compose1(
std::bind2nd(std::equal_to<int>(),value),
mem_data_ref(&foo::field)));

assert((*result).field==value);
}

  • 打赏
  • 举报
回复
HaoGeGe 2003-01-10
你说的的确有道理,
本来想用boost::bind的
但是在VC6上编译通不过.
不过遗憾的是vector不得不声明为包容指针的容器.
用起来梢感不方便.
总之谢谢你啦, 我想你一定是meta编程高手
  • 打赏
  • 举报
回复
anrxhzh 2003-01-10
目前的标准库对functional的支持还很不完善,仅仅提供了几个最基本的功能,即使是这样,很多编译器的实现依然不理想。鉴于这种情况,我倾向于保守的使用它,也就是说如果不是必要的,就不使用functional,而是自己写一个特定的function object。

在你的例子中,如果用上了SGI特有的扩展(compose),equal_helper_t就是多余的了。请看我的分析:
我们需要的是:h(x)=f(g(x),C),其中C是一个常量。而compose提供的是:
h(x)=f(g(x)),bind2st提供的是:h(x)=f(x,C),下面的数学推导是成立的:
h(x)=f(g(x),C) where g=mem_data
=bind2st(g(x))
=compose(x) where f=bind2st

源代码:
struct foo{
int field;
};

#include <vector>
#include <algorithm>
#include <cassert>

int main()
{
const int value=1;
foo f;
f.field=value;

using namespace std;

std::vector<foo*> V;
V.push_back(&f);

vector<foo*>::const_iterator result =
find_if(V.begin(), V.end(),
compose1(bind2nd(equal_to<int>(),value),mem_data(&foo::field)));

assert((*result)->field==value);
}


  • 打赏
  • 举报
回复
HaoGeGe 2003-01-10
to anrxhzh(百宝箱) : 谢谢你,太好了,我可以这样写程序了.
来不及简化和拓展但是可以成功了.
对于char field2 和 string field3 的查询例.

//-----------------------------------------------------------
template<typename R, typename T>
class mem_data_t : public std::unary_function<T*,R>{
public:
typedef R T::* pointer_type;
explicit mem_data_t(pointer_type p)
: ptr_(p) {}
R operator()(T * p) const
{return (p->*ptr_); }
private:
pointer_type ptr_;
};

template<typename R, typename T> inline
mem_data_t<R, T> mem_data(R T::* p)
{return (mem_data_t<R,T>(p)); }

//-----------------------------------------------------------//

struct foo{
int field1;
char field2;
string field3;
};

template<typename R, typename T>
class equal_helper_t : public std::unary_function<T*,R>{
public:
typedef R return_type;
explicit equal_helper_t(return_type r)
: ret_(r) {}
R operator()(T * p) const
{return (ret_); }
private:
return_type ret_;
};



int main()
{
foo f;
f.field1=1024;
f.field2 = 56;
f.field3 = "test";

vector<foo*> V;
V.push_back(&f);
f.field3 = "test2";
V.push_back(&f);
f.field3 = "test3";
V.push_back(&f);
//查询field3
vector<foo*>::iterator result =
find_if(V.begin(), V.end(),
compose2(equal_to<string>(), mem_data(&foo::field3),
equal_helper_t<string,foo>("test3")));
cout << (*result)->field3 << endl;
//查询field2
result = find_if(V.begin(), V.end(),
compose2(equal_to<char>(), mem_data(&foo::field2),
equal_helper_t<char,foo>(56)));
cout << (*result)->field2 << endl;
return 0;
}

  • 打赏
  • 举报
回复
HaoGeGe 2003-01-09
offsetof是宏而不是函数
所以是不是可以定义mem_data为宏呢?
  • 打赏
  • 举报
回复
luixui 2003-01-09
没有
  • 打赏
  • 举报
回复
widewave 2003-01-09
有道理!
  • 打赏
  • 举报
回复
HaoGeGe 2003-01-09
难道真的没有人做过这方面的研究吗?
难道真的无法实现吗?
  • 打赏
  • 举报
回复
anrxhzh 2003-01-09
我想可能有两个原因:
1.直接访问数据成员不太OO
2.mem_data,mem_fun这样的形式在现有的funtional库中的用途不大,比如很难直接写出这样的算法:find if mem greater than something
  • 打赏
  • 举报
回复
msftaovc 2003-01-09
up
  • 打赏
  • 举报
回复
solotony 2003-01-09
如果那样,你不如直接比较.何必放到类里面.
  • 打赏
  • 举报
回复
anrxhzh 2003-01-09
我也不知道为什么,不过可以自己实现一个。offsetof 不是一个C++解决方案,它只能用于POD[1]类型。

#include <functional>
#include <cassert>

//-----------------------------------------------------------
template<typename R, typename T>
class mem_data_t : public std::unary_function<T*,R>{
public:
typedef R T::* pointer_type;
explicit mem_data_t(pointer_type p)
: ptr_(p) {}
R operator()(T* p) const
{return (p->*ptr_); }
private:
pointer_type ptr_;
};

template<typename R, typename T> inline
mem_data_t<R, T> mem_data(R T::* p)
{return (mem_data_t<R,T>(p)); }

//-----------------------------------------------------------//

struct foo{
int field;
};

int main()
{
foo f;
f.field=1024;
assert(1024==mem_data(&foo::field)(&f));
}

[1]http://www-cpd.fnal.gov/personal/wb/boost/ISOcxx/doc/POD.html
  • 打赏
  • 举报
回复
HaoGeGe 2003-01-08
c++标准中有一个offsetof可以取得数据成员的偏移地址.
size_t offsetof( structName, memberName );
谁可以设计一个类似的mem_data出来啊!

  • 打赏
  • 举报
回复
Firstbyte 2003-01-08
up
  • 打赏
  • 举报
回复
sunwhite 2003-01-08
关注.............
  • 打赏
  • 举报
回复
发帖
工具平台和程序库

2.4w+

社区成员

C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
帖子事件
创建了帖子
2003-01-08 05:06
社区公告
暂无公告