STL-подобный диапазон, что может пойти не так, если я сделаю это? - PullRequest
5 голосов
/ 31 января 2010

Я пишу (как упражнение для самообучения) простой STL-подобный диапазон. Это «контейнер» с неизменяемым произвольным доступом. В моем диапазоне сохраняются только начальный элемент, количество элементов и размер шага (разница между двумя последовательными элементами):

struct range
{
...
private:
  value_type m_first_element, m_element_count, m_step;
};

Поскольку мой диапазон не содержит элементы, он вычисляет нужный элемент, используя следующее:

// In the standards, the operator[]
// should return a const reference.
// Because Range doesn't store its elements
// internally, we return a copy of the value.
value_type operator[](size_type index)
{
    return m_first_element + m_step*index;
}

Как видите, я не возвращаю const reference, как говорят стандарты. Теперь могу ли я предположить, что const reference и копия элемента одинаковы с точки зрения использования немутирующих алгоритмов в стандартной библиотеке?

Любые советы по этому вопросу приветствуются.


@ Стив Джессоп: Хорошо, что вы упомянули итераторы.

На самом деле, я использовал sgi в качестве ссылки . В конце этой страницы написано:

Предполагая, что x и y являются итераторами из одного диапазона:

Идентификация инвариантов
x == y if and only if &*x == &*y

Итак, все сводится к тому же самому первоначальному вопросу, который я задавал на самом деле:)

Ответы [ 4 ]

1 голос
/ 31 января 2010

Поскольку вы помещаете «контейнер» в «кавычки», вы можете делать все, что захотите.

Вещи типа STL (итераторы, различные функции-члены в контейнерах ..) возвращают ссылки, потому что ссылки являются lvalues, и тогда могут компилироваться определенные конструкции (т.е. myvec [i] = otherthing). Подумайте об операторе [] на std :: map. Полагаю, что для константных ссылок значение не просто избегать копирования.

Это правило все время нарушается, когда это удобно. Также обычно классы итераторов хранят текущее значение в переменной-члене исключительно с целью возврата ссылки или константной ссылки (да, эта ссылка будет недействительной, если итератор продвинутый).

Если вы заинтересованы в подобных вещах, вам следует проверить библиотеку буст-итераторов.

1 голос
/ 31 января 2010

Хотите ли вы, чтобы ваш диапазон можно было использовать в алгоритмах STL? Не было бы лучше с первым и последним элементами? (Учитывая тот факт, что end() часто требуется / используется, вам придется предварительно рассчитать его для производительности.) Или вы рассчитываете на смежные элементы (что является моим вторым пунктом)?

1 голос
/ 31 января 2010

Стандартные алгоритмы на самом деле не используют operator[], все они определены в терминах итераторов, если я не забыл что-то существенное. Планируется ли повторно реализовать стандартные алгоритмы поверх operator[] для ваших «диапазонов», а не итераторов?

В тех случаях, когда немутантные алгоритмы используют итераторы, все они определены в терминах *it, присваиваемых тому, что ему нужно назначить, или иным образом действительных для некоторой указанной операции или вызова функции. Я думаю, что все или большинство таких операций хороши со значением.

Единственное, о чем я могу думать, это то, что вы не можете передать значение, где ожидается неконстантная ссылка. Существуют ли алгоритмы без мутаций, которые требуют неконстантной ссылки? Вероятно, нет, при условии, что в любых параметрах функтора и т. Д. Содержится const.

Извините, я не могу однозначно сказать, что нет никаких странных углов, которые могут пойти не так, но для меня это звучит нормально. Даже если есть какие-то проблемы, вы можете исправить их с очень небольшими различиями в требованиях между вашими версиями алгоритмов и стандартными.

Редактировать: вторая вещь, которая может пойти не так, это взять указатели / ссылки и держать их слишком долго. Насколько я помню, стандартные алгоритмы не сохраняют указатели или ссылки на элементы - причина этого в том, что это контейнеры , которые гарантируют действительность указателей на элементы, типы итераторов сообщают вам только когда итератор остается действительным (например, копия входного итератора не обязательно остается действительной при увеличении оригинала, тогда как прямые итераторы могут быть скопированы таким образом для многопроходных алгоритмов). Поскольку алгоритмы не видят контейнеры, только итераторы, у них нет причин полагать, что элементы являются постоянными.

1 голос
/ 31 января 2010

Элементы в контейнерах STL должны постоянно копироваться; подумайте, например, когда нужно перераспределить вектор. Итак, ваш пример в порядке, за исключением того, что он работает только со случайными итераторами. Но я подозреваю, что последний, вероятно, разработан. : -Р

...