I am trying to write a class that should act as a sorted view on some underlying sequence of elements. So far I have come up with a non-const version. Now I have problems adapting it to also provide const_iterator functionality.
The code I have so far looks like this:
// forward declare iterator
template <class InputIt>
class sorted_range_iter;
template <class InputIt>
class sorted_range {
    friend class sorted_range_iter<InputIt>;
  private:
    using T = typename InputIt::value_type;
    InputIt _first;
    InputIt _last;
    std::vector<size_t> _indices;
  public:
    using iterator = sorted_range_iter<InputIt>;
    sorted_range() = default;
    sorted_range(InputIt first, InputIt last)
        : _first(first), _last(last), _indices(std::distance(_first, _last)) {
        std::iota(_indices.begin(), _indices.end(), 0);
    };
    template <class Compare = std::less<T>>
    void sort(Compare comp = Compare()) {
        std::sort(_indices.begin(), _indices.end(),
                  [this, &comp](size_t i1, size_t i2) {
                      return comp(*(_first + i1), *(_first + i2));
                  });
    }
    size_t size() const { return _indices.size(); }
    T& operator[](size_t pos) { return *(_first + _indices[pos]); }
    const T& operator[](size_t pos) const { return (*this)[pos]; }
    iterator begin() { return iterator(0, this); }
    iterator end() { return iterator(size(), this); }
};
And the corresponding iterator looks like this:
template <class InputIt>
class sorted_range_iter
    : public std::iterator<std::forward_iterator_tag, InputIt> {
    friend class sorted_range<InputIt>;
  private:
    using T = typename InputIt::value_type;
    size_t _index;
    sorted_range<InputIt>* _range;
    sorted_range_iter(size_t index, sorted_range<InputIt>* range)
        : _index(index), _range(range) {}
  public:
    T& operator*() { return *(_range->_first + _range->_indices[_index]); }
    // pre-increment
    const sorted_range_iter<InputIt>& operator++() {
        _index++;
        return *this;
    }
    // post-increment
    sorted_range_iter<InputIt> operator++(int) {
        sorted_range_iter<InputIt> result = *this;
        ++(*this);
        return result;
    }
    bool operator!=(const sorted_range_iter<InputIt>& other) const {
        return _index != other._index;
    }
};
An usage example looks like this:
std::vector<int> t{5, 2, 3, 4};
auto rit = ref.begin();
sorted_range<std::vector<int>::iterator> r(begin(t), end(t));
r.sort();
for(auto& x : r)
{
    std::cout << x << std::endl;
}
Output:
2
3
4
5
How do I adapt my iterator for the const case? It would be easier if the iterator would be templated on the underlying type (int for example) instead InputIt. Is there a better way to define this class?
I suppose one could solve this for example by using the range-v3 library, however I am trying to not add any more dependencies and rely on C++11/14 functions.
You just are using the wrong type for T. You have:
using T = typename InputIt::value_type;
But value_type is the same for iterator and const_iterator. What they have are different reference types. You should prefer:
using R = typename std::iterator_traits<InputIt>::reference;
R operator*() { ... }
This has the added benefit of working with pointers.
Alternatively, could avoid iterator_traits by just trying to dereference the iterator itself:
using R = decltype(*std::declval<InputIt>());
Side-note, shouldn't sorted_range sort itself on construction? Otherwise, easy to misuse. 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With