|
Boost : |
From: Shankar Sai (sai.shankar_at_[hidden])
Date: 2001-02-18 10:21:59
|> -----Original Message-----
|> From: Jens Maurer [mailto:Jens.Maurer_at_[hidden]]
|> Sent: Tuesday, February 13, 2001 1:24 AM
|> To: boost_at_[hidden]
|> Subject: Re: [boost] Adapters for member variables
|>
|>
|> Shankar Sai wrote:
|> > Is there any interest in a library that would enable
|> member variables
|> > to be used with the STL algorithms without having to write trivial
|> > functions? In case I'm not being clear <g>, here's an example.
|>
|> You have been advised of the lambda calculus libraries floating around.
|> However, I believe there may be a need for simple adapters
|> such as the one you propose for non-conforming compilers or minimizing
|> compile time.
|>
|> Please have a look at the function object and compose adapters already
|> present in boost for design guidance.
|>
|> http://www.boost.org/libs/functional/index.html
|> http://www.boost.org/libs/compose/index.htm
|>
|> It seems that the adapter compose_f_gx_hx probably does most of what
|> you want, so you may only need some functional wrapper around for
|> a data member.
Agreed.
|>
|> > template <class T, class Member, class Comp>
|> > struct member_comparer : public std::binary_function <T, T, bool>
|>
|> This interface does not seem flexible enough for the general case.
|> Don't you simply want some data_member<> template which just wraps
|> the member pointer?
|>
Agreed.
Thanks for the excellent comments. I didn't find time to do anything this
week, so the delayed posting. The idea is to enable writing code like the
following:
#include <string>
#include <iostream>
struct S
{
int column1_;
int column2_;
std::string column3_;
};
std::ostream& operator << (std::ostream& os, S const& s)
{
os << "\n" << s.column1_ << "\n";
os << s.column2_ << "\n";
os << s.column3_ << "\n\n";
return os;
}
#include <vector>
#include <algorithm>
#include <iterator>
#include "compose.hpp" // From Boost
int main ()
{
S x, y, z;
x.column1_ = -1;
y.column1_ = 0;
z.column1_ = 1;
x.column2_ = 0;
y.column2_ = 0;
z.column2_ = 0;
x.column3_ = "0";
y.column3_ = "1";
z.column3_ = "2";
std::vector <S> vec;
vec.push_back (x);
vec.push_back (y);
vec.push_back (z);
using boost::compose_f_gx_hx;
int count_of_column1_less_than_column2 =
std::count_if (vec.begin (), vec.end (),
compose_f_gx_hx (std::less <int> (),
data_member (&S::column1_),
data_member (&S::column2_)));
// Sort on column3 in descending order
using boost::compose_f_gx_hy;
std::sort (vec.begin (), vec.end (),
compose_f_gx_hy (std::greater <std::string> (),
data_member (&S::column3_),
data_member (&S::column3_)));
std::copy (vec.begin (),
vec.end (),
std::ostream_iterator <S> (std::cout));
}
The actual code is below. This code has been tested on MSVC (SP3),
g++ 2.95.2 on Cygwin(Windows NT), Borland 5.5 (SP2).
#include <functional>
template <class T, class Member>
struct data_member_t : public std::unary_function <T, Member&>
{
data_member_t (Member (T::*ptr)): ptr_(ptr)
{
}
Member& operator () (T const& t)
{
return t.*ptr_;
}
const Member& operator () (T const& t) const
{
return t.*ptr_;
}
Member T::*ptr_;
};
template <class T, class Member>
data_member_t <T, Member>
data_member (Member (T::*ptr))
{
return data_member_t <T, Member> (ptr);
}
Extensions i can think of are similar types/partial specializations
for handling pointers (dereferencing) and references (avoiding the
reference to a reference problem).
Contra: such members are not likely to be/should not be in "simple"
structs, which is what the adapter is aimed at. What do you think?
All comments/suggestions welcome.
Best Regards,
Sai Shankar
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk