Чтение онлайн

на главную - закладки

Жанры

Эффективное использование STL
Шрифт:

// и порядком сортировки, определяемым

// критерием StringPtrLess

// Вставить те же четыре строки

Теперь приведенный выше цикл будет работать именно так, как предполагалось (при условии, что ошибка была исправлена и вместо

*i
используется
**i
).

for (StringPtrSet::const_iterator i = ssp.begin;

 i != ssp.end; // Порядок вывода:

 ++i) // "Anteater", "Lemur",

 cout << **i << endl; // "Penguin", "Wombat"

Если

вы предпочитаете использовать алгоритм, напишите функцию, которая разыменовывает указатели
string*
перед выводом, а затем используйте ее в сочетании с
for_each
:

void print(const string *ps) // Вывести в cout объект,

{ // на который ссылается ps

 cout << *ps << endl;

}

for_each(ssp.begin, ssp.end, print); // Вызвать print для каждого

// элемента ssp

Существует более изощренное решение — обобщенный функтор разыменования, используемый с

transform
и
ostream_iterator
:

// Функтор получает T* и возвращает const T&

struct Dereference {

 template<typename T>

 const T& operator(const T* ptr) const {

return *ptr;

 }

};

transform(ssp.begin, ssp.end, // "Преобразовать" каждый

 ostream.iterator<string>(cout, "\n"), // элемент ssp посредством

 Dereference); // разыменования и записать

// результаты в cout

Впрочем, замена циклов алгоритмами будет подробно рассматриваться позднее, в совете 43. А сейчас речь идет о том, что при создании стандартного ассоциативного контейнера указателей следует помнить: содержимое контейнера будет сортироваться по значениям указателей. Вряд ли такой порядок сортировки вас устроит, поэтому почти всегда определяются классы-функторы, используемые в качестве типов сравнения.

Обратите внимание на термин «тип сравнения». Возможно, вас интересует, зачем возиться с созданием функтора вместо того, чтобы просто написать функцию сравнения для контейнера

set
? Например, так:

bool stringPtrLess(const string* ps1, // Предполагаемая функция сравнения

 const string* ps2) // для указателей string*,

{ // сортируемых по содержимому строки

 return *ps1 < *ps2;

}

set<string, stringPtrLess> ssp; // Попытка использования stringPtrLess

// в качестве функции сравнения ssp.

//
Не компилируется!!!

Проблема заключается в том, что каждый из трех параметров шаблона

set
должен быть типом. К сожалению,
stringPtrLess
— не тип, а функция, поэтому попытка задать
stringPtrLess
в качестве функции сравнения
set
не компилируется. Контейнеру
set
не нужна функция; ему нужен тип, на основании которого можно создатьфункцию.

Каждый раз, когда вы создаете ассоциативный контейнер указателей, помните о том, что вам, возможно, придется задать тип сравнения контейнера. В большинстве случаев тип сравнения сводится к разыменованию указателя и сравнению объектов, как это сделано в приведенном выше примере

StringPtrLess
. Шаблон для таких функторов сравнения стоит держать под рукой. Пример:

struct DereferenceLess {

 template <typename PtrType>

 bool operator(PtrType pT1, // Параметры передаются по значению.

PtrType рТ2) const // поскольку они должны быть

 { // указателями (или по крайней мере

return *рТ1 < *рТ2; // вести себя, как указатели)

 }

};

Данный шаблон снимает необходимость в написании таких классов, как

StringPtrLess
, поскольку вместо них можно использовать
DereferenceLess
:

set<string*, DereferenceLess> ssp; // Ведет себя так же, как

// set<string*, stringPtrLess>

И последнее замечание. Данный совет посвящен ассоциативным контейнерам указателей, но он в равной степени относится и к контейнерам объектов, которые ведут себя как указатели (например, умные указатели и итераторы). Если у вас имеется ассоциативный контейнер умных указателей или итераторов, подумайте, не стоит ли задать тип сравнения и для него. К счастью, решение, приведенное для указателей, работает и для объектов-аналогов. Если определение

DereferenceLess
подходит в качестве типа сравнения для ассоциативного контейнера
T*
, оно с большой вероятностью подойдет и для контейнеров итераторов и умных указателей на объекты
T
.

Совет 21. Следите за тем, чтобы функции сравнения возвращали false в случае равенства

Сейчас я покажу вам нечто любопытное. Создайте контейнер

set
с типом сравнения
less_equal
и вставьте в него число 10:

set<int, less_equal<int> > s; // Контейнер s сортируется по критерию "<="

s.insert(10); // Вставка числа 10

Теперь попробуйте вставить число 10 повторно:

s.insert(10);

Поделиться:
Популярные книги

Хранилище

Старухин Евгений
5. Лесовик
Фантастика:
фэнтези
рпг
7.43
рейтинг книги
Хранилище

Морской волк. 1-я Трилогия

Савин Владислав
1. Морской волк
Фантастика:
альтернативная история
8.71
рейтинг книги
Морской волк. 1-я Трилогия

Искатель 1

Шиленко Сергей
1. Валинор
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Искатель 1

Анти-Ксенонская Инициатива

Вайс Александр
7. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Анти-Ксенонская Инициатива

На границе империй. Том 10. Часть 8

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 8

Мастер решений

Земляной Андрей Борисович
3. Специалист по выживанию
Фантастика:
боевая фантастика
космическая фантастика
6.20
рейтинг книги
Мастер решений

Барон нарушает правила

Ренгач Евгений
3. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон нарушает правила

Хозяин Теней

Петров Максим Николаевич
1. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней

Последний реанорец. Том IX

Павлов Вел
8. Высшая Речь
Фантастика:
фэнтези
попаданцы
аниме
5.75
рейтинг книги
Последний реанорец. Том IX

Я до сих пор князь. Книга XXII

Дрейк Сириус
22. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я до сих пор князь. Книга XXII

Источник

Билик Дмитрий Александрович
11. Бедовый
Фантастика:
юмористическое фэнтези
городское фэнтези
мистика
7.00
рейтинг книги
Источник

Неучтенный элемент. Том 10

NikL
10. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 10

Последний Паладин. Том 13

Саваровский Роман
13. Путь Паладина
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 13

Дитя прибоя

Трофимов Ерофей
Дитя прибоя
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Дитя прибоя