Итератор, который выдает только одно значение?

#c #c 17

#c #c 17

Вопрос:

Некоторые алгоритмы STL (и подобные STL алгоритмы, которые можно придумать в других контекстах) принимают свои входные данные через итераторы. Иногда я ловлю себя на том, что хочу передать (const) итератор в качестве одного из своих входных данных, который просто продолжает выдавать одно и то же значение (или постоянную ссылку на одно и то же значение в памяти). Вы можете использовать это, например, для реализации std::fill с использованием std::copy_n и std::distance (при условии, что у вас есть конец вашей цели).

Итак, есть ли это где-нибудь в стандартной библиотеке или в одном из TS’es (C 17 или более ранней версии)?

Примечание: я говорю не о постоянном итераторе, а скорее об итераторе, который никогда не продвигается и продолжает выдавать одно и то же.

Комментарии:

1. Какие «алгоритмы STL» вы имеете в виду? Практически все, что я знаю, действительно, продвинет или иным образом вычислит что-то, связанное с итератором. Не было бы смысла объявлять библиотечную функцию, которая принимает значение итератора, только для его разыменования и ничего с ним не делать в противном случае. Я думаю, вы что-то недопонимаете.

2. @SamVarshavchik: См. Редактирование.

3. Ваше редактирование ничего не объясняет, на какие конкретные «алгоритмы STL» вы смотрите.

4. Если вы попытаетесь передать неинкрементируемый / декрементируемый итератор функции, которая должна продвигать указанный итератор, то это просто не сработает.

5. @Archiepiskopofbanterbury: На самом деле я уже приводил неверный пример. Давайте попробуем еще один.

Ответ №1:

Просто создайте класс, реализующий интерфейс прямого итератора, оператор разыменования которого возвращает ваше единственное значение.

Ответ №2:

В этом примере реализован самый простой интерфейс итератора, std::iterator .

Аргумент ssize_t в подписи — это тип, который следует использовать для различий, потому что даже это не зафиксировано в STL 🙂

Сколько значений он возвращает, определяется поведением operator == в сочетании со значением, возвращаемым методом end() .

 template <typename E>
class IteratorExample
{
    ...

    struct StlIterator
    {
        ...

        const E amp; operator * ()
        {
            ...
        }

        const E * operator -> ()
        {
            return amp;(operator * ());
        }

        StlIterator amp; operator    ()
        {
            ...
        }

        StlIterator amp; operator    (int)
        {
            ...
        }

        bool operator == (const StlIterator amp;other)
        {
            ...
        }

        bool operator != (const StlIterator amp;other)
        {
            return (operator == (other)) == false;
        }

        typedef E value_type;
        typedef size_t difference_type;
        typedef E * pointer;
        typedef E amp; reference;
        typedef std::input_iterator_tag iterator_category;
    };

    StlIterator begin() const
    {
        return StlIterator(...);
    }

    StlIterator end() const
    {
        return StlIterator(...);
    }
};
 

Комментарии:

1. Разве std::iterator не будет устаревшим в C 17?

2. Да, но мы пока не знаем, будет ли новый удобный механизм, заменяющий свойства итератора, или нам действительно придется писать тонны шаблонов для каждого итератора…

3. Просто модернизировал его для вас 🙂

4. Честно говоря, я просто модернизировал его для себя в своем реальном коде, поэтому я не получаю предупреждение, когда c 17 становится новым стандартом 😬

5. Я на самом деле не понимаю, какой метод ref<Iterator> используется. Это так std::ref ? откуда берется тип итератора? Где находится iter поле? Как поле и параметр могут иметь одно и то же имя?

Ответ №3:

Для copy_n первого параметра должен удовлетворять требованиям InputIterator . Однако следующий пример представляет собой минимальную рабочую реализацию, в которой отсутствуют некоторые требования InputIterator :

 #include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
template <typename T, T t>
struct It:public std::iterator<std::input_iterator_tag, T>
{
    constexpr autoamp; operator  () const{
        return *this;
    }
    constexpr autoamp; operator (size_t) const{
        return *this;
    }
    constexpr auto operator*() const{
        return t;
    }
};


int main(){
 //an iterator with constant value of 1
    It<int,1> in;
    std::vector<int> out;
    std::copy_n(in, 4, std::back_inserter(out));
}