Совет 36. Правильно реализуйте copy_if
Совет 36. Правильно реализуйте copy_if
В STL имеется 11 алгоритмов, в именах которых присутствует слово сору:
сору cop_backward
replace_copy reverse_copy
replace_copy_if unique_copy
remove_copy rotate_copy
remove_copy_if partial_sort_copy
uninitialzed_copy
Но как ни странно, алгоритма copy_if среди них нет. Таким образом, вы можете вызывать replace_copy_if и remove_copy_if, к вашим услугам copy_backward и reverse_copy, но если вдруг потребуется просто скопировать элементы интервала, удовлетворяющие определенному предикату, вам придется действовать самостоятельно.
Предположим, имеется функция для отбора «дефектных» объектов Widget:
bool isDefective(const Widget& w);
Требуется скопировать все дефектные объекты Widget из вектора в cerr. Если бы алгоритм copy_if существовал, это можно было бы сделать так:
vector<Widget> widgets;
copy_if(widgets.begin(),widgets.end(),// He компилируется -
ostream_iterator<Widget>(cerr," ").// в STL не существует
isDefective);// алгоритма copy_if
По иронии судьбы алгоритм copy_if входил в исходную версию STL от Hewlett Packard, которая была заложена в основу библиотеки STL, ставшей частью стандартной библиотеки С++. В процессе сокращения HP STL до размеров, подходящих для стандартизации, алгоритм copy_if остался за бортом.
В книге «The С++ Programming Language» [7] Страуструп замечает, что реализация copy_if выглядит элементарно — и он прав, но это вовсе не означает, что каждый программист сразу придет к нужному решению. Например, ниже приведена вполне разумная версия copy_if, которую предлагали многие программисты (в том числе и я):
template<typename InputIterator,// Не совсем правильная
typename OutputIterator,// реализация copy_if
typename Predicate>
OutputIterator copy_if(InputIterator begin,
InputIterator end,
OutputIterator destBegin,
Predicate p)
{
return remove_copy_if(begin,end,destBegin,not1(p));
}
Решение основано на простом факте: хотя STL не позволяет сказать «скопировать все элементы, для которых предикат равен true», но зато можно потребовать «скопировать все элементы, кроме тех, для которых предикат неравен true». Создается впечатление, что для реализации copy_if достаточно поставить not1 перед предикатом, который должен передаваться copy_if, после чего передать полученный предикат remove_copy_if. Результатом является приведенный выше код.
Если бы эти рассуждения были верны, копирование дефектных объектов Widget можно было бы произвести следующим образом:
copy_if(widgets.begin(),.widgets.end(),// Хорошо задумано,
ostream_iterator<Widget>(cerr," "), // но не компилируется
isDefective);
Компилятор недоволен попыткой применения not1 к isDefective (это происходит внутри copy_if). Как объясняется в совете 41, not1 не может напрямую применяться к указателю на функцию — сначала указатель должен пройти через ptr_fun. Чтобы вызвать эту реализацию copy_if, необходимо передать не просто объект функции, а адаптируемый объект функции. Сделать это несложно, однако возлагать эти хлопоты на будущих клиентов алгоритма STL нельзя. Стандартные алгоритмы STL никогда не требуют, чтобы их функторы были адаптируемыми, поэтому нельзя предъявлять это требование к copy_if. Приведенная выше реализация хороша, но недостаточно хороша.
Правильная реализация copy_if должна выглядеть так:
template<typename InputIterator,// Правильная
typename OutputIterator,// реализация copy_if
typename Predicate> OutputIterator copy_if(InputIterator begin.
InputIterator end, OutputIterator destBegin. Predicate p)
{
while begin!=end) { f(p(*begin)) *destBegn++ = *begin; ++begin;
}
return destBegn;
}
Поскольку алгоритм copy_if чрезвычайно полезен, а неопытные программисты STL часто полагают, что он входит в библиотеку, можно порекомендовать разместить реализацию copy_if — правильную реализацию! — в локальной вспомогательной библиотеке и использовать ее в случае надобности.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Глава 3 Как правильно скачивать
Глава 3 Как правильно скачивать Практически все файлы, за исключением расположенных в пиринговых сетях, можно загрузить средствами самого браузера — программы, с помощью которой вы бороздите просторы Интернета. Загрузить доступный файл проще простого — щелкнул кнопкой
Как правильно настроить программу
Как правильно настроить программу Лучше всего, конечно, настроить программу изначально. По крайней мере, так вы сможете присвоить себе удобочитаемый ник, который будет виден всем остальным участникам разговора, не говоря уже о других полезных настройках, которые зависят
2.2.17. Как правильно выбрать площадку
2.2.17. Как правильно выбрать площадку Выбрать площадку для размещения рекламы – далеко не самое легкое дело. Сейчас контекстная реклама переживает период подъема и бурного развития. Из-за этого систем контекстной рекламы становится все больше и больше, причем каждую
Правильно ли составлен ваш текст?
Правильно ли составлен ваш текст? Чтобы информация достигла цели, мало будет удивить центр Брока. Еще нужно сделать продающий текст убедительным, значимым для покупателя и хорошо оформленным.Чтение – это главное занятие пользователей Интернета. Некоторые посетители
Как правильно провести тестирование
Как правильно провести тестирование Теперь вы видите, насколько полезными могут быть тесты. Положим, вы решили применить свои знания на практике, но не до конца в себе уверены. Например, как вы докажете остальным, что результаты тестирования являются верными? При
Как правильно вести блог?
Как правильно вести блог? Главным преимуществом блогосферы является то, что ее пользователям предоставлена полная свобода действий. Ведь далеко не все ресурсы, предназначенные для общения (форумы и т.п.) позволяют своим пользователям писать все, что угодно – прежде всего
Как правильно продвигать «молодой» сайт
Как правильно продвигать «молодой» сайт Продвигать «молодые» сайты непросто, так как поисковые системы при ранжировании сайтов учитывают их возраст. Это связано с тем, что в Интернете полно нулевых сайтов, которые создаются исключительно для манипулирования поисковой
Совет 35. Реализуйте простые сравнения строк без учета регистра символов с использованием mismatch или lexicographical_compare
Совет 35. Реализуйте простые сравнения строк без учета регистра символов с использованием mismatch или lexicographical_compare Один из вопросов, часто задаваемых новичками в STL — «Как в STL сравниваются строки без учета регистра символов?» Простота этого вопроса обманчива. Сравнения
Совет 39. Реализуйте предикаты в виде «чистых» функций
Совет 39. Реализуйте предикаты в виде «чистых» функций Для начала разберемся с основными терминами.Предикатом называется функция, возвращающая тип bool (или другое значение, которое может быть автоматически преобразовано к bool). Предикаты широко используются в STL. В
9. Как правильно пользоваться функциями
9. Как правильно пользоваться функциями ФУНКЦИИСТРОИТЕЛЬНЫЕ БЛОКИ ПРОГРАММЫСВЯЗЬ МЕЖДУ ФУНКЦИЯМИ: АРГУМЕНТЫ, УКАЗАТЕЛИ, ВОЗВРАТ ЗНАЧЕНИЯТИПЫ
Как правильно провести собеседование?
Как правильно провести собеседование? Собеседование, или интервью, является одним из важнейших этапов отбора кандидатов, и от умения его грамотно провести во многом зависит правильность выбора того или иного кандидата.В общем случае собеседованию можно дать следующее
3.7. Правильно включаем компьютер
3.7. Правильно включаем компьютер Вы соединили все части своего ПК. Вот теперь можно включить питание (надеюсь, вы не забыли подключить самый главный кабель — кабель питания?). На передней панели системного блока (рис. 27) есть кнопка Power. Ее и надо нажать для включения
3.8. Правильно выключаем
3.8. Правильно выключаем Нельзя просто вытащить шнур питания компьютера из розетки! Нужно правильно завершить работу компьютера. Для корректного завершения работы нужно выполнить следующие действия:нажать кнопку Пуск в левом нижнем углу экрана;выбрать Выключение
Проводить ее правильно
Проводить ее правильно Без правильных процедур ваши люди легко могут пропустить важные шаги при проведении ими аудита. В результате этого у вас могут появиться двойные запоры на дверях при широко открытых окнах. Чтобы этого избежать, обеспечьте наличие подробных
Как правильно удалять программы
Как правильно удалять программы Для удаления программы следует запустить специальную утилиту деинсталляции, которая удалит файлы приложения, записи в реестре, а также значки в меню Пуск ина Рабочем столе. Начинающие пользователи при удалении программ допускают две
«Питайтесь правильно»
«Питайтесь правильно» Программа «Питайтесь правильно» (рис. 5.2) считает калории, белки, жиры и углеводы в заданном рационе. Она умеет определять норму по калориям и питательным веществам на основе заданных персональных данных о пользователе, которые позволят определить