Эффективное использование STL [Скотт Мейерс] (fb2) читать постранично, страница - 106
[Настройки текста] [Cбросить фильтры]
SpecialContainer<Widget> scw; vw.insert(vw.begin(), scw.begin(), scw.end()); // Присоединить к vw копию // объектов Widget из scw Подобная универсальность объясняется тем, что интервальная функция insert контейнера range вообще не является функцией в общепринятом смысле. Это шаблон функции контейнера, специализация которого с произвольным типом итератора порождает конкретную интервальную функцию insert. Для контейнера vector шаблон insert объявлен в Стандарте следующим образом: template <class T, class Allocator = allocator<T> > class vector { public: … template<class InputIterator> void insert(iterator position, InputIterator first, InputIterator last); }; Каждый стандартный контейнер должен поддерживать шаблонную версию интервальной функции insert. Аналогичные шаблоны также обязательны для интервальных конструкторов и для интервальной формы assign (см. совет 5).
MSVC версий 4-6
К сожалению, в реализации STL, входящей в комплект поставки версий 4-6, шаблоны функций не объявляются. Библиотека изначально разрабатывалась для MSVC версии 4, а этот компилятор, как и большинство компиляторов того времени, не обладал поддержкой шаблонов функций классов. При переходе от MSCV4 к MSVC6 поддержка этих шаблонов была включена в компилятор, но вследствие судебных дел, косвенно затрагивавших фирму Microsoft, библиотека оставалась практически в неизменном состоянии. Поскольку реализация STL, поставляемая с MSVC4-6, предназначалась для компилятора без поддержки шаблонов функций классов, авторы библиотеки имитировали эти шаблоны и заменили их конкретными функциями, которым при вызове передавались итераторы контейнера соответствующего типа. Например, шаблон insert был заменен следующей функцией: void insert(iterator position, // "iterator" - тип итератора iterator first, iterator last); // для конкретного контейнера Эта ограниченная форма интервальных функций позволяла выполнить интервальную вставку из vector<Widget> в vector<Widget> или из list<int> в list<int>, но смешанные операции (например, вставка из vector<Widget> в list<Widget> или из set<int> в deque<int>) не поддерживались. Более того, не поддерживалась даже интервальная вставка (а также конструирование или assign) из vector<long> в vector<int>, поскольку итераторы vector<long>::iterator и vector<int>::iterator относятся к разным типам. В результате следующий фрагмент, принимаемый другими компиляторами, не компилируется в MSVC4-6: istream_iterator<Widget> begin(cin), end; // Создать итераторы begin и end // для чтения объектов Widget // из cin (см. совет 6). vector<Widget> vw(begin, end); // Прочитать объекты Widget // из cin в vw (см. совет 6) // не компилируется в MSVC4-6! list<Widget> lw; lw.assign(vw.rbegin(), vw.rend()); // Присвоить lw содержимое vw // (в обратном порядке); // не компилируется в MSVC4-6! SpeciаlContainer<Widget> scw; scw.insert(scw.end(), lw.begin(), lw.end()); // Вставить в конец scw // копию объектов Widget из lw; // не компилируется в MSVC4-6! Так что же делать, если вы работаете в среде MSVC4-6? Это зависит от используемой версии MSVC и того, вынуждены ли вы использовать реализацию STL, поставляемую вместе с компилятором.Обходное решение для MSVC4-5
Еще раз посмотрим на правильный код, который не компилируется для реализации STL из поставки MSVC4-6: vector<Widget> vw(begin, end); // Отвергается реализацией STL // из поставки MSVC4-6 list<Widget> lw; … lw.assign(vw.rbegin(), vw.rend()); // То жеSpeciаlContainer<Widget> scw; … scw.insert(scw.end(), lw.begin(), lw.end()); // То же Несмотря на внешние различия, выделенные вызовы отвергаются компилятором по одной и той же причине: из-за отсутствия шаблонов функций класса в реализации STL. Соответственно и решение во всех случаях оказывается одним и тем же: замена вызовом copy с итератором вставки (см. совет 30). Ниже приведены обходные решения для всех примеров, приведенных ранее: istream_iterator<Widget> begin(cin), end; vector<Widget> vw(begin, end); //Создать vw конструктором copy(begin, end, back_inserter(vw)); // по умолчанию и скопировать // в него объекты Widget из cin list<Widget> lw; … lw.clear(); // Удалить из lw старые объекты; copy(vw.rbegin(), vw.rend(), // скопировать объекты из vw back_inserter(lw)); //(в обратном порядке) SpecialContainer<Widget> scw; copy(lw.begin(), lw.end(), // Скопировать
Последние комментарии
3 часов 22 минут назад
3 часов 24 минут назад
4 часов 22 минут назад
4 часов 45 минут назад
22 часов 44 минут назад
22 часов 45 минут назад