#ifndef INCLUDED_BOBCAT_PTRITER_
#define INCLUDED_BOBCAT_PTRITER_

#include <iterator>

namespace FBB
{
template <typename Iterator>
struct PtrIter
{
    using iterator_category = std::input_iterator_tag;
    using difference_type   = std::ptrdiff_t;
    using value_type        = decltype(&*Iterator());
    using pointer           = value_type *;
    using reference         = value_type &;


    private:
        Iterator d_iter;

    public:
        using PtrType = decltype(&*Iterator());

        PtrIter(Iterator const &iter);                                  // 1.f
        PtrIter(PtrIter &&tmp)          = default;
        PtrIter(PtrIter const &other)   = default;

        PtrType operator*() const;                              //    opstar.f

        PtrIter &operator++();                                      // opinc.f

        bool operator==(PtrIter const &other) const;                //  opeq.f
        bool operator!=(PtrIter const &other) const;                // opneq.f
};

template <typename Iterator>
PtrIter<Iterator>::PtrIter(Iterator const &iter)
:
    d_iter(iter)
{}

template <typename Iterator>
bool PtrIter<Iterator>::operator==(PtrIter const &other) const
{
    return d_iter == other.d_iter;
}
template <typename Iterator>
PtrIter<Iterator> &PtrIter<Iterator>::operator++()
{
    ++d_iter;
    return *this;
}
template <typename Iterator>
bool PtrIter<Iterator>::operator!=(PtrIter const &other) const
{
    return d_iter != other.d_iter;
}
template <typename Iterator>
typename PtrIter<Iterator>::PtrType PtrIter<Iterator>::operator*() const
{
    return &*d_iter;
}

    // Free functions

template<typename Iterator>
PtrIter<Iterator> ptrIter(Iterator const &iter)
{
    return PtrIter<Iterator>(iter);
}


} // FBB
#endif
