Алгоритм lexicographical_compareявляется обобщенной версией strcmp. Функция strcmpработает только с символьными массивами, а lexicographical_compareработает с интервалами значений любого типа. Кроме того, если strcmpвсегда сравнивает два символа и определяет отношение между ними (равенство, меньше, больше), то lexicographical_compareможет получать произвольный предикат, который определяет, удовлетворяют ли два значения пользовательскому критерию.
В предыдущем примере алгоритм lexicographical_compareдолжен найти первую позицию, в которой s1и s2различаются по критерию ciCharLess. Если для символов в этой позиции ciCharLessвозвращает true, то же самое делает и lexicographical_compare: если в первой позиции, где символы различаются, символ первой строки предшествует соответствующему символу второй строки, то первая строка предшествует второй. Алгоритм lexicographical_compare, как и strcmp, считает два интервала равных величин равными, поэтому для таких интервалов возвращается значение false: первый интервал не предшествует второму. Кроме того, по аналогии с strcmp, если первый интервал завершается до обнаружения различия, lexicographical_compareвозвращает true— префикс предшествует любому интервалу, в который он входит.
Довольно о mismatchи lexicographical_compare. Хотя в этой книге большое значение уделяется переносимости программ, я просто обязан упомянуть о том, что функции сравнения строк без учета регистра символов присутствуют во многих нестандартных расширениях стандартной библиотеки C. Обычно эти функции называются stricmpили strcmpiи по аналогии с функциями, приведенными в данном совете, игнорируют проблемы интернационализации. Если вы готовы частично пожертвовать переносимостью программы, если строки заведомо не содержат внутренних нуль-символов, а проблемы интернационализации вас не волнуют, то простейший способ сравнения строк без учета регистра символов вообще не связан с STL. Обе строки преобразуются в указатели const char*(см. совет 16), передаваемые при вызове stricmpили strcmpi:
int ciStringCompare(const string& si1, const string& s2) {
return stricmp(sl.c_str(), s2.c_str());// В вашей системе вместо stricmp
} // может использоваться другое имя
Функции strcmp/strcmp, оптимизированные для выполнения единственной задачи, обычно обрабатывают длинные строки значительно быстрее, чем обобщенные алгоритмы mismatchи lexicographical_compare. Если быстродействие особенно важно в вашей ситуации, переход от стандартных алгоритмов STL к нестандартным функциям C вполне оправдан. Иногда самый эффективный путь использования STL заключается в том, чтобы вовремя понять, что другие способы работают лучше.
Совет 36. Правильно реализуйте copy_if
В STL имеется 11 алгоритмов, в именах которых присутствует слово copy:
copy copy_backward
replace_copy reverse_copy
replace_copy_if unique_copy
remove_copy rotate_copy
remove_copy_if partial_sort_copy
uninitialized_copy
Но как ни странно, алгоритма copy_ifсреди них нет. Таким образом, вы можете вызывать replace_copy_ifи remove_copy_if, к вашим услугам copy_backwardи reverse_copy, но если вдруг потребуется просто скопировать элементы интервала, удовлетворяющие определенному предикату, вам придется действовать самостоятельно.
Предположим, имеется функция для отбора «дефектных» объектов Widget:
bool isDefective(const Widget& w);
Требуется скопировать все дефектные объекты Widgetиз вектора в cerr. Если бы алгоритм copy_ifсуществовал, это можно было бы сделать так:
vector widgets;
…
copy_if(widgets.begin(), widgets.end(), // He компилируется -
ostream_iterator(cerr, "\n"), // в STL не существует
isDefective); // алгоритма copy_if
По иронии судьбы алгоритм copy_ifвходил в исходную версию STL от Hewlett Packard, которая была заложена в основу библиотеки STL, ставшей частью стандартной библиотеки C++. В процессе сокращения HP STL до размеров, подходящих для стандартизации, алгоритм copy_ifостался за бортом.
В книге «The C++ Programming Language» [7] Страуструп замечает, что реализация copy_ifвыглядит элементарно — и он прав, но это вовсе не означает, что каждый программист сразу придет к нужному решению. Например, ниже приведена вполне разумная версия copy_if, которую предлагали многие программисты (в том числе и я):
Читать дальше