vector vw1, vw2;
…
vw1.insert(vw1.end(), vw2.begin(), vw2.end()); // Присоединить к vw1 копию
// объектов Widget из vw2
Аналогичную операцию можно выполнить с контейнерами vector
и deque
:
vector vw;
deque dw;
…
vw.insert(vw.end(), dw.begin(), dw.end()); // Присоединить к vw копию
// объектов Widget из dw
Оказывается, эту операцию можно выполнить независимо от того, в каких контейнерах хранятся копируемые объекты. Подходят даже нестандартные контейнеры:
vector vw;
…
list lw;
…
vw.insert(vw.begin(), lw.begin(), lw.end()); // Присоединить к vw копию
// объектов Widget из lw
set sw;
…
vw.insert(vw.begin(), sw.begin(), sw.end()); // Присоединить к vw копию
// объектов Widget из sw
template
typename Allocator = allocator > // Шаблон нестандартного
class SpecialContainer{…}; // STL-совместимого контейнера
SpecialContainer scw;
vw.insert(vw.begin(), scw.begin(), scw.end()); // Присоединить к vw копию
// объектов Widget из scw
Подобная универсальность объясняется тем, что интервальная функция insert
контейнера range
вообще не является функцией в общепринятом смысле. Это шаблон функции контейнера, специализация которого с произвольным типом итератора порождает конкретную интервальную функцию insert
. Для контейнера vector
шаблон insert
объявлен в Стандарте следующим образом:
template >
class vector {
public:
…
template
void insert(iterator position, InputIterator first, InputIterator last);
};
Каждый стандартный контейнер должен поддерживать шаблонную версию интервальной функции insert
. Аналогичные шаблоны также обязательны для интервальных конструкторов и для интервальной формы assign
(см. совет 5).
К сожалению, в реализации STL, входящей в комплект поставки версий 4-6, шаблоны функций не объявляются. Библиотека изначально разрабатывалась для MSVC версии 4, а этот компилятор, как и большинство компиляторов того времени, не обладал поддержкой шаблонов функций классов. При переходе от MSCV4 к MSVC6 поддержка этих шаблонов была включена в компилятор, но вследствие судебных дел, косвенно затрагивавших фирму Microsoft, библиотека оставалась практически в неизменном состоянии.
Поскольку реализация STL, поставляемая с MSVC4-6, предназначалась для компилятора без поддержки шаблонов функций классов, авторы библиотеки имитировали эти шаблоны и заменили их конкретными функциями, которым при вызове передавались итераторы контейнера соответствующего типа. Например, шаблон insert
был заменен следующей функцией:
void insert(iterator position, // "iterator" - тип итератора
iterator first, iterator last); // для конкретного контейнера
Эта ограниченная форма интервальных функций позволяла выполнить интервальную вставку из vector
в vector
или из list
в list
, но смешанные операции (например, вставка из vector
в list
или из set
в deque
) не поддерживались. Более того, не поддерживалась даже интервальная вставка (а также конструирование или assign
) из vector
в vector
, поскольку итераторы vector::iterator
и vector::iterator
относятся к разным типам. В результате следующий фрагмент, принимаемый другими компиляторами, не компилируется в MSVC4-6:
istream_iterator begin(cin), end; // Создать итераторы begin и end
// для чтения объектов Widget
// из cin (см. совет 6).
vector vw(begin, end); // Прочитать объекты Widget
// из cin в vw (см. совет 6)
// не компилируется в MSVC4-6!
list lw;
lw.assign(vw.rbegin(), vw.rend()); // Присвоить lw содержимое vw
// (в обратном порядке);
// не компилируется в MSVC4-6!
SpeciаlContainer scw;
scw.insert(scw.end(), lw.begin(), lw.end()); // Вставить в конец scw
// копию объектов Widget из lw;
// не компилируется в MSVC4-6!
Так что же делать, если вы работаете в среде MSVC4-6? Это зависит от используемой версии MSVC и того, вынуждены ли вы использовать реализацию STL, поставляемую вместе с компилятором.
Обходное решение для MSVC4-5
Читать дальше