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