Я реализовал пользовательский итератор, основанный на ответе здесь:
{ ссылка }
Однако вместо члена Type* _ptr
мой код в конечном итоге получает значение хранится в каком-то единственном месте, как если бы он использовал следующую функцию:
// my iterator class gets its values from this function
float globalFloat{ 0 };
float* retrieveFloat (int idx)
{
globalFloat = (float)idx;
return &globalFloat;
}
Это означает, что для одновременного использования двух итераторов (т. е. для поиска с использованием upper_bound), я должен кешировать локально перед тем, как разрешить доступ:
class Iterator : public std::iterator<std::random_access_iterator_tag, float, int>
{
public:
Iterator () = default;
Iterator (int idx) : _index (idx) {}
Iterator& operator++ () noexcept { ++_index; return *this; }
Iterator& operator-- () noexcept { --_index; return *this; }
/// ... rest of iterator declaration
const float& operator* () const { _data = *retrieveFloat (_index); return _data; }
const float* operator-> () const { _data = *retrieveFloat (_index); return &this->_data; }
const float& operator[] (int offset) const { _data = *retrieveFloat (_index + offset); return _data; }
private:
int _index{ 0 };
mutable float _data{ 0 };
};
Меня беспокоит последний оператор []. Согласно cppreference:
https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
оператор [] должен возвращать ссылочный тип. Однако, если бы я написал следующий код:
int main (int argc, char ** argv)
{
Iterator it;
if (it[0] == it[1])
return 0;
return 1;
}
Тогда я верну 0, потому что каждый вызов [] изменяет _data.
Если я изменю способ подкласса std :: iterator и использую float в качестве моего "ссылочного" типа:
class Iterator : public std::iterator<std::random_access_iterator_tag, float, int, float*, float>
{
public:
/// ... rest of iterator declaration (constructors / operators)
const float operator* () const { _data = *retrieveFloat (_index); return _data; }
const float* operator-> () const { _data = *retrieveFloat (_index); return &this->_data; }
const float operator[] (int offset) const { _data = *retrieveFloat (_index + offset); return _data; }
};
, тогда все будет работать ... но почему-то это выглядит грязно. Делать подобные вещи законно?
Я знаю, что если бы вместо float мой тип данных был чем-то более тяжелым для копирования, то возникла бы проблема с производительностью, но ради аргумента скажем, что я работаю только с float или облегченными POD. Давайте также предположим, что мне не нужно изменять итерируемые данные.
Спасибо за любую помощь, которую вы можете оказать, и извините, если я задал этот вопрос слишком долго. Я могу редактировать, если это будет необходимо.