Скотт Мейерс - Эффективное использование STL
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(), // Скопировать объекты Widget
inserter(scw, scw.end())); // из lw в конец scw
Я рекомендую использовать эти обходные решения с библиотекой, входящей в комплект поставки MSVC4-5. С другой стороны, будьте внимательны и не забывайте о том, что эти решения являются обходными. Как показано в совете 5, алгоритм copy почти всегда уступает интервальной функции контейнера, поэтому как только представится возможность обновить платформу STL до версии с поддержкой шаблонов функций класса, откажитесь от использования copy в тех местах, где следовало бы использовать интервальные функции.
Обходное решение для MSVC6
Обходное решение из предыдущего раздела подходит и для MSVC6, но в этом случае существует и другой вариант. Компиляторы MSVC4-5 не обладают полноценной поддержкой шаблонов функций класса, поэтому отсутствие этих шаблонов в реализации STL несущественно. В MSVC6 дело обстоит иначе, поскольку компилятор этой среды поддерживает шаблоны функций класса. Таким образом, возникает естественное желание заменить реализацию STL из поставки MSVC6 другой реализацией с шаблонами функций классов, предписанными Стандартом.
В совете 50 упоминаются свободно распространяемые реализации STL от SGI и STLport; в списках поддерживаемых компиляторов обеих реализаций упоминается MSVC6. Кроме того, можно приобрести новейшую MSVC-совместимую реализацию STL от Dinkumware. У каждого из этих вариантов есть свои достоинства и недостатки.
Реализации SGI и STLport распространяются бесплатно, поэтому какая-либо официальная поддержка в этих случаях попросту отсутствует. Более того, поскольку реализации SGI и STLport рассчитаны на работу с разными компиляторами, вам придется дополнительно настроить их для обеспечения максимального быстродействия в MSVC6. В частности, может потребоваться включение поддержки шаблонов функций классов — из-за совместимости с большим количеством разных компиляторов в SGI и/или STLport эта поддержка отключена по умолчанию. Возможно, также придется позаботиться о компоновке с другими библиотеками MSVC6 (особенно DLL), проследить за использованием соответствующих версий для отладки и т. д.
Если подобные вещи вас пугают или вы руководствуетесь принципом «бесплатные программы обходятся слишком дорого», рассмотрите альтернативную реализацию STL для MSVC6 от Dinkumware. Библиотека проектировалась с расчетом на максимальную простоту замены и на соответствие Стандарту. Реализация STL из MSVC6 разрабатывалась именно в Dinkumware, поэтому вполне возможно, что новая реализация STL действительно легко заменяет оригинал. За дополнительной информацией о реализациях STL от Dunkumware обращайтесь на сайт компании http://www.dunkumware.com.
Независимо от того, на какой реализации вы остановите свой выбор, вы получите нечто большее, чем STL с шаблонами функций классов. В альтернативных реализациях будут решены проблемы соответствия Стандарту в других областях — скажем, отсутствие объявления push_back в контейнере string. Более того, в вашем распоряжении окажутся полезные расширения STL, в том числе хэшированные контейнеры (см. совет 25) и односвязные списки (контейнер slist). Реализации SGI и STLport также содержат множество нестандартных классов функторов, включая select1st и select2nd (см. совет 50).
Но даже если вы вынуждены работать с реализацией STL из поставки MSVC6, сайт Dunkumware все же стоит посетить. На нем перечислены известные ошибки в реализации библиотеки MSVC6 и приведены рекомендации относительно того, как модифицировать библиотеку для сокращения ее недостатков. Не стоит и говорить, что редактирование заголовочных файлов библиотеки — дело весьма рискованное. Если у вас возникнут проблемы, не вините в них меня.
Примечания
1
В среде программистов данный термин (англ. mutex) встречается также в варианте «мутекс». — Примеч. ред.
2
Строго говоря, не все 24 перестановки равновероятны, так что вероятность 1/24 не совсем точна. Тем не менее, остается бесспорный факт: существуют 24 разные перестановки, и вы можете получить любую из них.
3
Термин употребляется в статистике. — Примеч. ред.
4
Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. «Приемы объектно-ориентированного проектирования. Паттерны проектирования» — СПб.: Питер, 2001.
5
См. статью Александреску A. (Andrei Alexandrescu) в майском номере «C++ Report» за 2000 г. [19].
6
Внимание: в шаблоне функции use_facet параметр шаблона присутствует только в типе возвращаемого значения, но не в аргументах. При обращении к нему используется языковое средство, называ-емоеявяьш заданием аргументов шаблона, которое не поддерживается некоторыми компиляторами C++. Если ваш компилятор принадлежит к их числу, возможно, авторы реализации библиотеки предусмотрели обходное решение, которое позволяет использовать use_facet другим способом.