Должны ли ForwardIterators быть OutputIterators? Моя текущая STL-реализация (VS2012) выводится forward_iterator_tag
от обоих input_iterator_tag
а также output_iterator_tag
, но я не могу найти это требование в стандарте [N3485].
В C ++ 11 нет, прямые итераторы не обязаны быть выходными итераторами. Выходные требования к итератору подобны дополнительному набору требований, которые может иметь итератор, независимо от остальных требований итератора, которым он соответствует. Прямые итераторы должны быть только входными итераторами (§24.2.5 / 1):
Класс X или указатель типа X удовлетворяет требованиям прямого итератора, если:
- X удовлетворяет требованиям входного итератора
- …
Фактически, прямой итератор удовлетворяет требованиям выходного итератора, только если он является изменяемым итератором для последовательности типов, назначаемых для копирования.†.
† или постоянный итератор для последовательности типов с operator=(...) const
определяется с изменяемыми членами.
Более конкретно, теги итератора определяются конкретно стандартом как (§24.4.3 / 2):
namespace std {
struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag: public input_iterator_tag { };
struct bidirectional_iterator_tag: public forward_iterator_tag { };
struct random_access_iterator_tag: public bidirectional_iterator_tag { };
}
Как вы видете, forward_iterator_tag
должно наследоваться только от input_iterator_tag
,
В C ++ 03 указано, что прямые итераторы удовлетворяют требованиям итераторов ввода и вывода:
Прямые итераторы удовлетворяют всем требованиям итераторов ввода и вывода и могут использоваться всякий раз, когда указывается любой вид.
Но это затем противоречит следующему абзацу, утверждая, что постоянный прямой итератор не удовлетворяет требованиям для выходных итераторов:
Помимо своей категории, итератор прямого, двунаправленного или произвольного доступа также может быть изменяемым или постоянным в зависимости от того, действует ли результат выражения * i как ссылка или как ссылка на константу. Постоянные итераторы не удовлетворяют требованиям для выходных итераторов, и результат выражения * i (для постоянного итератора i) нельзя использовать в выражении, где требуется lvalue.
Однако определение тегов итератора такое же, как и в C ++ 11. Был отчет о дефектах для этой противоречивой формулировки, но она была закрыта как Не Дефект, потому что первая цитата находится во «вводном тексте» раздела и, вероятно, будет переписана в будущем (как это было).
Определение SGI прямого итератора дается как уточнение итераторов ввода и вывода (благодаря @BenVoigt в комментариях).
Тем не менее, если мы посмотрим на реализация тегов итератора, мы находим, что forward_iterator_tag
все еще наследует только от input_iterator_tag
,
Похоже, это было областью путаницы в прошлом, но если VS2012 определяет forward_iterator_tag
как наследование от обоих output_
— а также input_iterator_tag
Я могу только предположить, что это ошибка.
Других решений пока нет …