Boost logo

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.
|> 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.


|> > 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?


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

#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, gregod at, cpdaniel at, john at