Joshua
open source statistical hierarchical phrase-based machine translation system
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
src/kenlm/util/proxy_iterator.hh
00001 #ifndef UTIL_PROXY_ITERATOR_H
00002 #define UTIL_PROXY_ITERATOR_H
00003 
00004 #include <cstddef>
00005 #include <iterator>
00006 
00007 /* This is a RandomAccessIterator that uses a proxy to access the underlying
00008  * data.  Useful for packing data at bit offsets but still using STL
00009  * algorithms.
00010  *
00011  * Normally I would use boost::iterator_facade but some people are too lazy to
00012  * install boost and still want to use my language model.  It's amazing how
00013  * many operators an iterator has.
00014  *
00015  * The Proxy needs to provide:
00016  *   class InnerIterator;
00017  *   InnerIterator &Inner();
00018  *   const InnerIterator &Inner() const;
00019  *
00020  * InnerIterator has to implement:
00021  *   operator==(InnerIterator)
00022  *   operator<(InnerIterator)
00023  *   operator+=(std::ptrdiff_t)
00024  *   operator-(InnerIterator)
00025  * and of course whatever Proxy needs to dereference it.
00026  *
00027  * It's also a good idea to specialize std::swap for Proxy.
00028  */
00029 
00030 namespace util {
00031 template <class Proxy> class ProxyIterator {
00032   private:
00033     // Self.
00034     typedef ProxyIterator<Proxy> S;
00035     typedef typename Proxy::InnerIterator InnerIterator;
00036 
00037   public:
00038     typedef std::random_access_iterator_tag iterator_category;
00039     typedef typename Proxy::value_type value_type;
00040     typedef std::ptrdiff_t difference_type;
00041     typedef Proxy reference;
00042     typedef ProxyIterator<Proxy> * pointer;
00043 
00044     ProxyIterator() {}
00045 
00046     // For cast from non const to const.
00047     template <class AlternateProxy> ProxyIterator(const ProxyIterator<AlternateProxy> &in) : p_(*in) {}
00048     explicit ProxyIterator(const Proxy &p) : p_(p) {}
00049 
00050 /*    // p_'s swap does value swapping, but here we want iterator swapping
00051     friend inline void swap(ProxyIterator<Proxy> &first, ProxyIterator<Proxy> &second) {
00052       swap(first.I(), second.I());
00053     }*/
00054 
00055     // p_'s operator= does value copying, but here we want iterator copying.
00056     S &operator=(const S &other) {
00057       I() = other.I();
00058       return *this;
00059     }
00060 
00061     bool operator==(const S &other) const { return I() == other.I(); }
00062     bool operator!=(const S &other) const { return !(*this == other); }
00063     bool operator<(const S &other) const { return I() < other.I(); }
00064     bool operator>(const S &other) const { return other < *this; }
00065     bool operator<=(const S &other) const { return !(*this > other); }
00066     bool operator>=(const S &other) const { return !(*this < other); }
00067 
00068     S &operator++() { return *this += 1; }
00069     S operator++(int) { S ret(*this); ++*this; return ret; }
00070     S &operator+=(std::ptrdiff_t amount) { I() += amount; return *this; }
00071     S operator+(std::ptrdiff_t amount) const { S ret(*this); ret += amount; return ret; }
00072 
00073     S &operator--() { return *this -= 1; }
00074     S operator--(int) { S ret(*this); --*this; return ret; }
00075     S &operator-=(std::ptrdiff_t amount) { I() += (-amount); return *this; }
00076     S operator-(std::ptrdiff_t amount) const { S ret(*this); ret -= amount; return ret; }
00077 
00078     std::ptrdiff_t operator-(const S &other) const { return I() - other.I(); }
00079 
00080     Proxy operator*() { return p_; }
00081     const Proxy operator*() const { return p_; }
00082     Proxy *operator->() { return &p_; }
00083     const Proxy *operator->() const { return &p_; }
00084     Proxy operator[](std::ptrdiff_t amount) const { return *(*this + amount); }
00085 
00086     const InnerIterator &Inner() { return p_.Inner(); }
00087 
00088   private:
00089     InnerIterator &I() { return p_.Inner(); }
00090     const InnerIterator &I() const { return p_.Inner(); }
00091 
00092     Proxy p_;
00093 };
00094 
00095 template <class Proxy> ProxyIterator<Proxy> operator+(std::ptrdiff_t amount, const ProxyIterator<Proxy> &it) {
00096   return it + amount;
00097 }
00098 
00099 } // namespace util
00100 
00101 #endif // UTIL_PROXY_ITERATOR_H