Создание произвольного итератора const - PullRequest
0 голосов
/ 18 апреля 2020

Предположим, у меня есть шаблонная функция, у которой есть параметр, используемый в качестве итератора (хотя и без каких-либо концепций / требований - C ++ 17 или более ранних версий) с именем my_iter.

Могу ли я в общем убедиться, что итератор такое константный итератор, или получить константный итератор в той же позиции?

Примечание: В отличие от этот вопрос , который касается iterator против const_iterator некоторых предположительно известных контейнерный класс, здесь мы не знаем, что это за контейнерный класс, если он вообще существует. Поэтому я не хочу писать что-то вроде:

auto it = std::cbegin(my_container);
auto desired_iter = it + distance(it, my_iter);

, как предложено в , этот метод , и даже:

auto desired_iter = ContainerType::const_iterator(my_iter);

1 Ответ

1 голос
/ 18 апреля 2020

Вы можете создать класс-оболочку ConstIterator для обеспечения правильности const:

#include <list>
#include <iostream>
#include <string>

template <typename Iterator>
class ConstIterator {
public:
        ConstIterator(Iterator const it) /* Not explicit */
                : it_{ it }
        {}

        auto& operator++() noexcept
        {
                ++it_;
                return *this;
        }

        [[nodiscard]] auto operator++(int) noexcept
        {
                auto copy = *this;
                ++it_;
                return copy;
        }

        auto& operator--() noexcept
        {
                --it_;
                return *this;
        }

        [[nodiscard]] auto operator--(int) noexcept
        {
                auto copy = *this;
                --it_;
                return copy;
        }

        [[nodiscard]] auto const& operator*() const noexcept
        {
                return *it_;
        }

        auto const* operator->() const noexcept
        {
                return &*it_; // const pointer
        }

        auto& operator+= (std::size_t const step) noexcept
        {
                it_ += step;
                return *this;
        }

        auto& operator-= (std::size_t const step) noexcept
        {
                it_ -= step;
                return *this;
        }

        auto operator+ (std::size_t const step) noexcept
        {
                auto copy = *this;
                return copy += step;
        }

        auto operator- (std::size_t const step) noexcept
        {
                auto copy = *this;
                return copy -= step;
        }

        auto operator- (ConstIterator const rhs) noexcept
        {
                return it_ - rhs.it_;
        }


        auto operator == (ConstIterator const rhs) noexcept
        {
                return it_ == rhs.it_;
        }

        auto operator != (ConstIterator const rhs) noexcept
        {
                return !(*this == rhs);
        }

private:
        Iterator it_;
};


// test it
template<typename Iter>
void print(Iter beg, Iter end) noexcept
{

        ConstIterator<Iter> cbeg{ beg }; // const iterator

        for (auto it = cbeg; it != end; ++it) {
                std::cout << *it << ' '; // accessing works fine
        }
        std::cout << '\n';


        // cbeg->clear(); // won't compile
        // *cbeg = decltype(*cbeg){}; // won't compile
}


int main()
{
        std::list<std::string> list{"1", "2", "3"};
        print(list.begin(), list.end());
}
...