field.cpp

(plain text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <functional>

//! Template for function objects which, when called with an object,
//! apply a given pointer-to-member to that object.
template <typename C, typename R>
class mem_field_t : public std::unary_function<C, R> {
public:
  //! Record a pointer to a member of C of type R.
  explicit mem_field_t (R C::*field) : myField(field) { }
  //! Apply the given pointer-to-member to the given object.
  R &operator() (C &x) const { return x .* myField; }
  //! Apply the given pointer-to-member to the given object.
  const R &operator() (const C &x) const { return x .* myField; }

private:
  R C::*myField;
};
  
//! Generate a mem_field_t function object for the given pointer-to-member.
template <typename C, typename R>
mem_field_t<C, R>
mem_field (R C::*p) {
  return mem_field_t<C, R>(p);
}

//////////////////////////////////////////////////////////////////////

#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <boost/bind.hpp>
#include <boost/iterator_adaptors.hpp>

struct Drive;

struct get_second 
  : std::unary_function<std::map<int, Drive *>::value_type, Drive *> { 
  result_type operator() (argument_type p) const { return p.second; } 
}; 

int main () {
  typedef std::map<int, Drive *> map_type;
  typedef map_type::value_type map_value_type;
  map_type map;
  std::list<Drive *> list;

  // - std::transform
  //   o with get_second
  std::transform(map.begin(), map.end(), std::back_inserter(list),
		 get_second());
  //   o with mem_field
  std::transform(map.begin(), map.end(), std::back_inserter(list),
		 mem_field(&map_value_type::second));
  //   o with boost::bind
  std::transform(map.begin(), map.end(), std::back_inserter(list),
		 boost::bind(&map_value_type::second, _1));
  // - std::copy
  //   o with get_second
  std::copy(boost::make_transform_iterator
	    (map.begin(), mem_field(&map_value_type::second)),
	    boost::make_transform_iterator
	    (map.end(),   mem_field(&map_value_type::second)),
	    std::back_inserter(list));
  //   o with mem_field
  std::copy(boost::make_transform_iterator(map.begin(), get_second()),
	    boost::make_transform_iterator(map.end(), get_second()),
	    std::back_inserter(list));
  //   o with boost::bind
  //     x doesn't compile: "forming pointer to reference type"
#if 0
  std::copy(boost::make_transform_iterator
	    (map.begin(), boost::bind(&map_value_type::second, _1)),
	    boost::make_transform_iterator
	    (map.end(),   boost::bind(&map_value_type::second, _1)),
	    std::back_inserter(list));
#endif
}