libmoost
/home/mhx/git/github/libmoost/include/moost/which.hpp
Go to the documentation of this file.
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__