Почему стандарт не позволяет std :: for_each иметь четко определенное поведение на недопустимых диапазонах итераторов произвольного доступа? - PullRequest
3 голосов
/ 07 февраля 2012

В этом вопросе было объяснено, что std :: for_each имеет неопределенное поведение при задании недопустимого диапазона итератора [first, last) (то есть когда последний недоступен при увеличении first).

Предположительно, это связано с тем, что общий цикл for(auto it = first; it != last; ++it) будет работать вечно в недопустимых диапазонах.Но для итераторов с произвольным доступом это кажется ненужным ограничением, поскольку итераторы с произвольным доступом имеют оператор сравнения, и можно было бы записать явные циклы как for(auto it = first; it < last; ++it).Это превратит цикл по недопустимому диапазону в недопустимый.

Итак, мой вопрос: почему стандарт не позволяет std :: for_each иметь четко определенное поведение в недопустимых диапазонах итераторов произвольного доступа?Это упростит несколько алгоритмов, которые имеют смысл только для многоэлементных контейнеров (например, сортировка).Существует ли снижение производительности за использование оператора <() вместо оператора! = ()? </p>

Ответы [ 3 ]

4 голосов
/ 07 февраля 2012

Это превратит цикл по недопустимому диапазону в безоперационный.

Это не обязательно так.

Один из примеров недопустимого диапазона - это когдаfirst и last относятся к разным контейнерам.Сравнение таких итераторов приведет к неопределенному поведению по крайней мере , в некоторых случаях .

2 голосов
/ 07 февраля 2012

Это превратит цикл по недопустимому диапазону в безоперационный.

Вы, кажется, говорите, что operator< всегда должен возвращать false для двух произвольного доступаитераторы, которые не являются частью одного диапазона.Это единственный способ, которым указанный цикл был бы неработоспособен.

Стандарт не имеет смысла указывать это.Помните, что указатели являются итераторами с произвольным доступом.Подумайте о бремени реализации операций с указателями и общей путанице, которая возникает у читателей, если было определено, что следующий код выводит «два»:

int a[5];
int b[5]; // neither [a,b) nor [b,a) is a valid range
if ((a < b) || (b < a)) {
    std::cout << "one\n";
} else {
    std::cout << "two\n";
}

Вместо этого он остается неопределенным, чтобы люди выиграли 'Во-первых, напиши это.

2 голосов
/ 07 февраля 2012

Потому что это общая политика. Все использование < позволит как:

std::for_each( v.begin() + 20, v.begin() + 10, op );

Даже с <, передачей неверного итератора или итераторов из разных контейнеры, это неопределенное поведение.

...