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



и >multimap приходится обходиться без оператора [ ], поскольку эта функция существует только в >map.

Согласитесь, игра не стоит свеч. Контейнеры действительно отличаются друг от друга, обладают разными достоинствами и недостатками. Они не были рассчитаны на взаимозаменяемость, и с этим фактом остается только смириться. Любые попытки лишь искушают судьбу, а она этого не любит.

Но рано или поздно наступит день, когда окажется, что первоначальный выбор контейнера был, мягко говоря, не оптимальным, и вы захотите переключиться на другой тип. При изменении типа контейнера нужно не только исправить ошибки, обнаруженные компилятором, но и проанализировать весь код, где он используется, и разобраться, что следует изменить в свете характеристик нового контейнера и правил перехода итераторов, указателей и ссылок в недействительное состояние. Переходя с >vector на другой тип контейнера, вы уже не сможете рассчитывать на С-совместимую структуру памяти, а при обратном переходе нужно проследить за тем, чтобы контейнер не использовался для хранения >bool.

Если вы знаете, что тип контейнера в будущем может измениться, эти изменения можно упростить обычным способом — инкапсуляцией. Одно из простейших решений основано на использовании определений >typedef для типов контейнера и итератора. Следовательно, фрагмент

>class Widget{...};

>vector vw;

>Widget bestWidget;

>… // Присвоить значение bestWidget

>vector::iterator i =// Найти Widget с таким же значением,

>find(vw.begin(),vw.end().bestWidget) // как у bestWidget

записывается в следующем виде:

>class Widget{...};

>typedef vector WidgetContaner;

>typedef WidgetContainer:.iterator WCIterator;

>WidgetContaner vw;

>Widget bestWidget;

>WCIterator i =find(vw.begin().vw.end(),bestWidget):

Подобная запись значительно упрощает изменение типа контейнера, что особенно удобно, когда изменение сводится к простому добавлению нестандартного распределителя памяти (такое изменение не влияет на правила недействительности итераторов/указателей/ссылок).

>class Widget{...};

>template// В совете 10 объясняется, почему

>Specia1Anocator{...}; // необходимо использовать шаблон

>typedef vector.Specia1Anocator WidgetContainer;

>typedef WidgetContainer::iterator WCIterator;

>WidgetContainer vw;// Работает

>Widget bestWidget;

>WCIterator i=find(vw.begin().vw.end().bestWidget); // Работает

Даже если вас не интересуют аспекты >typedef, связанные с инкапсуляцией, вы наверняка оцените экономию времени. Предположим, у вас имеется объект типа