ostream.iterator
Dereference); // разыменования и записать
// результаты в cout
Впрочем, замена циклов алгоритмами будет подробно рассматриваться позднее, в совете 43. А сейчас речь идет о том, что при создании стандартного ассоциативного контейнера указателей следует помнить: содержимое контейнера будет сортироваться по значениям указателей. Вряд ли такой порядок сортировки вас устроит, поэтому почти всегда определяются классы-функторы, используемые в качестве типов сравнения.
Обратите внимание на термин set
? Например, так:
bool stringPtrLess(const string* ps1, // Предполагаемая функция сравнения
const string* ps2) // для указателей string*,
{ // сортируемых по содержимому строки
return *ps1 < *ps2;
}
set
// в качестве функции сравнения ssp.
// Не компилируется!!!
Проблема заключается в том, что каждый из трех параметров шаблона set
должен быть stringPtrLess
— не тип, а функция, поэтому попытка задать stringPtrLess
в качестве функции сравнения set
не компилируется. Контейнеру set
не нужна функция; ему нужен тип, на основании которого можно
Каждый раз, когда вы создаете ассоциативный контейнер указателей, помните о том, что вам, возможно, придется задать тип сравнения контейнера. В большинстве случаев тип сравнения сводится к разыменованию указателя и сравнению объектов, как это сделано в приведенном выше примере StringPtrLess
. Шаблон для таких функторов сравнения стоит держать под рукой. Пример:
struct DereferenceLess {
template
bool operator(PtrType pT1, // Параметры передаются по значению.
PtrType рТ2) const // поскольку они должны быть
{ // указателями (или по крайней мере
return *рТ1 < *рТ2; // вести себя, как указатели)
}
};
Данный шаблон снимает необходимость в написании таких классов, как StringPtrLess
, поскольку вместо них можно использовать DereferenceLess
:
set
// set
И последнее замечание. Данный совет посвящен ассоциативным контейнерам указателей, но он в равной степени относится и к контейнерам объектов, которые DereferenceLess
подходит в качестве типа сравнения для ассоциативного контейнера T*
, оно с большой вероятностью подойдет и для контейнеров итераторов и умных указателей на объекты T
.
Совет 21. Следите за тем, чтобы функции сравнения возвращали false в случае равенства
Сейчас я покажу вам нечто любопытное. Создайте контейнер set
с типом сравнения less_equal
и вставьте в него число 10:
set
s.insert(10); // Вставка числа 10
Теперь попробуйте вставить число 10 повторно:
s.insert(10);
При этом вызове insert
контейнер должен выяснить, присутствует ли в нем число 10. Мы знаем, что такое число уже есть, но контейнер глуп как пробка и все проверяет лично. Чтобы вам было проще понять, что при этом происходит, назовем первоначально вставленный экземпляр 10A, а новый экземпляр — 10B.