簡體   English   中英

C ++范圍排序視圖-如何創建const_iterator?

[英]c++ sorted view of range - how to create const_iterator?

我正在嘗試編寫一個類,該類應充當元素的某些基礎序列的排序視圖。 到目前為止,我想出了一個非const版本。 現在,我在調整它以提供const_iterator功能方面遇到問題。

到目前為止,我的代碼如下所示:

// 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); }
};

相應的迭代器如下所示:

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;
    }
};

一個用法示例如下所示:

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;
}

輸出:

2
3
4
5

如何針對const情況調整迭代器? 如果將迭代器模板InputIt基礎類型(例如int )而不是InputIt ,將更加容易。 有沒有更好的方法來定義此類?

我想可以例如通過使用range-v3庫來解決此問題,但是我試圖不添加任何依賴關系,而是依靠C ++ 11/14函數。

您只是為T使用了錯誤的類型。 你有:

using T = typename InputIt::value_type;

但是value_type對於iteratorconst_iterator相同。 它們具有不同的引用類型。 您應該更喜歡:

using R = typename std::iterator_traits<InputIt>::reference;

R operator*() { ... }

這具有使用指針的額外好處。

或者,可以通過嘗試取消對迭代器本身的引用來避免iterator_traits

using R = decltype(*std::declval<InputIt>());

旁注, sorted_range不應該在構造時sorted_range排序嗎? 否則,容易被濫用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM