Эффективное использование STL | страница 18



и >lower_bound — только ассоциативными контейнерами и т. д. Даже сигнатуры таких базовых операций, как >insert и >erase, зависят от категории. Например, в последовательном контейнере вставленный объект остается в исходной позиции, тогда как в ассоциативном контейнере он перемещается в позицию, соответствующую порядку сортировки данного контейнера. Или другой пример: форма erase, которой при вызове передается итератор, для последовательного контейнера возвращает новый итератор, но для ассоциативного контейнера не возвращается ничего (в совете 9 показано, как это обстоятельство влияет на программный код).

Допустим, вас посетила творческая мысль — написать код, который работал бы со всеми распространенными последовательными контейнерами: >vector, >deque и >list. Разумеется, вам придется программировать в контексте общих возможностей этих контейнеров, а значит, функции >reserve и >capacity (совет 14) использовать нельзя, поскольку они не поддерживаются контейнерами >deque и >list. Присутствие >list также означает, что вам придется отказаться от оператора [] и ограничиться двусторонними итераторами, что исключает алгоритмы, работающие с итераторами произвольного доступа — >sort, >stable_sort, >patial_sort и >nth_element (совет 31).

С другой стороны, исходное намерение поддерживать >vector исключает функции >pushfront и >popfont; >vector и >deque исключают применение >splice и реализацию >sort внутри контейнера. Учитывая те ограничения, о которых говорилось выше, последний запрет означает, что для вашего «обобщенного последовательного контейнера» не удастся вызвать никакую форму >sort.

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

В разных последовательных контейнерах действуют разные правила недействительности итераторов, указателей и ссылок. Чтобы ваш код правильно работал с >vector, >deque и >list, необходимо предположить, что любая операция, приводящая к появлению недействительных итераторов, указателей и ссылок в любом из этих контейнеров, приведет к тем же последствиям и в используемом контейнере. Отсюда следует, что после каждого вызова >insert недействительным становится абсолютно все, поскольку >deque:: insert делает недействительными все итераторы, а из-за невозможности использования