c++ 范围的排序 View - 如何创建 const_iterator?

标签 c++ stl iterator c++14 const-iterator

我正在尝试编写一个类,该类应充当某些基础元素序列的排序 View 。到目前为止,我提出了一个非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 的情况?如果将迭代器模板化为基础类型(例如 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 不应该在构建时自行排序吗?否则,容易误用。

关于c++ 范围的排序 View - 如何创建 const_iterator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33020424/

相关文章:

c++ - 计算这个字符串匹配函数的大 O 复杂度?

c++ - std::transform 一元操作签名

c++ - 将 Qt 与 STL 和 Boost 混合使用 - 是否有任何桥梁可以让它变得简单?

C++ 迭代 vector 返回甚至不在 vector 中的对象

c++ - 在 C++ 迭代器中,我应该同时定义 operator== 和 operator!= 吗?

C++ 异或运算符优先级

C++,如何优化浮点算术运算?

c++ - 为什么在插入 map 时出现段错误?

c++ - 在 C++ 中收集模式元素

c++ - 如何更改对 (> 和 <) 运算符的行为?