Вход/Регистрация
Эффективное использование STL
вернуться

Мейерс Скотт

Шрифт:

Если вы хотите сохранить указатели

string*
в контейнере
set
так, чтобы их порядок определялся значениями строк, стандартный функтор сравнения
less<string*>
вам не подойдет. Вместо этого необходимо написать собственный функтор сравнения, который получает указатели
string*
и упорядочивает их по содержимому строк, на которые они ссылаются. Пример:

struct StringPtrLess:

 public binary_function<const string*, // Базовый класс

 const string*, // описан в совете 40

 bool> {

 bool operator (const string *ps1, const string *ps2) const {

return *ps1 < *ps2:

 }

};

После этого

StringPtrLess
используется в качестве типа критерия сравнения
ssp
:

typedef set<string*, StringPtrLess> StringPtrSet;

StringPtrSet ssp; // Создать множество с объектами string

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

// критерием 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
не нужна функция; ему нужен тип, на основании которого можно создатьфункцию.

  • Читать дальше
  • 1
  • ...
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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