libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_WHICH_H__ 00029 #define MOOST_WHICH_H__ 00030 00031 #include <utility> // for pair 00032 #include <functional> // for less 00033 #include <iterator> // for iterator_traits 00034 00035 namespace moost { 00036 00045 template<int N> 00046 struct which; 00047 00048 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00049 00050 template <typename Cont, int N> 00051 class which_back_inserter_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void> 00052 { 00053 Cont& container_; 00054 which<N> which_; 00055 public: 00056 which_back_inserter_iterator(Cont& container) : container_(container) {} 00057 which_back_inserter_iterator& operator*() { return *this; } 00058 which_back_inserter_iterator& operator++() { return *this; } 00059 which_back_inserter_iterator& operator++(int) { return *this; } 00060 00061 template <typename T1, typename T2> 00062 which_back_inserter_iterator & operator=(const std::pair<T1, T2>& value) 00063 { 00064 container_.push_back( which_(value) ); 00065 return *this; 00066 } 00067 }; 00068 00069 00070 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00071 00072 template <typename Cont, int N> 00073 class which_inserter_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void> 00074 { 00075 Cont& container_; 00076 typename Cont::iterator where_; 00077 which<N> which_; 00078 00079 public: 00080 which_inserter_iterator(Cont& container, typename Cont::iterator where) : container_(container), where_(where) {} 00081 which_inserter_iterator& operator*() { return *this; } 00082 which_inserter_iterator& operator++() { return *this; } 00083 which_inserter_iterator& operator++(int) { return *this; } 00084 template <typename T1, typename T2> 00085 which_inserter_iterator & operator=(const std::pair<T1, T2>& value) 00086 { 00087 where_ = container_.insert( where_, which_(value) ); 00088 ++where_; 00089 return *this; 00090 } 00091 }; 00092 00093 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 00094 00095 namespace detail { 00096 00097 template<class Pair, int N> 00098 struct which_helper; 00099 00100 template<class Pair> 00101 struct which_helper<Pair, 1> 00102 { 00103 typedef typename Pair::first_type type; 00104 static type Pair::*member() 00105 { 00106 return &Pair::first; 00107 } 00108 }; 00109 00110 template<class Pair> 00111 struct which_helper<Pair, 2> 00112 { 00113 typedef typename Pair::second_type type; 00114 static type Pair::*member() 00115 { 00116 return &Pair::second; 00117 } 00118 }; 00119 } 00120 00121 template<int N> 00122 struct which 00123 { 00124 typedef which<3-N> other_type; 00125 00127 template<typename Pair> 00128 typename detail::which_helper<Pair, N>::type & operator()(Pair & el) const 00129 { 00130 return el.*detail::which_helper<Pair, N>::member(); 00131 } 00132 00134 template<typename Pair> 00135 typename detail::which_helper<Pair, N>::type const & operator()(Pair const & el) const 00136 { 00137 return el.*detail::which_helper<Pair, N>::member(); 00138 } 00139 00140 struct iterator_accessor 00141 { 00143 template<typename IT> 00144 typename detail::which_helper<typename std::iterator_traits<IT>::value_type, N>::type & 00145 operator()(IT & el) const 00146 { 00147 return el->*detail::which_helper<typename std::iterator_traits<IT>::value_type, N>::member(); 00148 } 00149 00151 template<typename IT> 00152 typename detail::which_helper<typename std::iterator_traits<IT>::value_type, N>::type const & 00153 operator()(IT const & el) const 00154 { 00155 return el->*detail::which_helper<typename std::iterator_traits<IT>::value_type, N>::member(); 00156 } 00157 }; 00158 00160 template< template <class> class Pred = std::less> 00161 struct comparer 00162 { 00163 template <typename Pair> 00164 bool operator()(Pair const & lhs, Pair const & rhs ) const 00165 { 00166 return Pred<typename detail::which_helper<Pair, N>::type>()( 00167 lhs.*detail::which_helper<Pair, N>::member(), 00168 rhs.*detail::which_helper<Pair, N>::member()); 00169 } 00170 }; 00171 00173 template <typename T, template <class> class Pred = std::equal_to> 00174 class value_comparer 00175 { 00176 public: 00177 value_comparer(const T& value) 00178 : m_value(value) 00179 {} 00180 00181 template <typename Pair> 00182 bool operator()(Pair const & val) const 00183 { 00184 return Pred<T>()(val.*detail::which_helper<Pair, N>::member(), m_value); 00185 } 00186 00187 private: 00188 const T& m_value; 00189 }; 00190 00191 template<typename Cont> 00192 static which_back_inserter_iterator<Cont, N> back_inserter(Cont& container) 00193 { // return a back_insert_iterator 00194 return (which_back_inserter_iterator<Cont, N>(container)); 00195 } 00196 00197 template<typename Cont, typename Iterator> 00198 static which_inserter_iterator<Cont, N> inserter(Cont& container, Iterator where) 00199 { // return a back_insert_iterator 00200 return (which_inserter_iterator<Cont, N>(container, where)); 00201 } 00202 00203 }; 00204 00205 } // moost 00206 00207 #endif // MOOST_WHICH_H__