Однако в других контекстах стиль не является единственным фактором. Во избежание потенциальных неоднозначностей лексического анализа (я избавлю вас от подробностей) имена типов, зависящие от формальных параметров шаблона, должны предваряться ключевым словом typename. Такие типы называются зависимыми типами. Небольшой пример поможет вам лучше понять, о чем идет речь. Предположим, вы пишете шаблон функции, которая получает контейнер STL и возвращает результат проверки условия «последний элемент контейнера больше первого». Одно из возможных решений выглядит так:

template

bool latGreaterThanFirst(const С& container)

{

if(container.empty()) return false:

typename C::const_iterator begin(container.begin());

typename C::const_iterator end(container.end());

return *--end > *begin;

}

В этом примере локальные переменные begin и end относятся к типу С::const_iterator, зависящему от формального параметра С. Поскольку тип С:: const_iterator является зависимым, перед ним должно стоять ключевое слово typename. Некоторые компиляторы принимают код без typename, но такой код не переносится на другие платформы.

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

В книге часто встречаются параметры lhs и rhs. Эти сокращения означают «left-hand side» («левая сторона») и «right-hand side» («правая сторона») соответственно, они особенно удобны при объявлении операторов. Пример из совета 19:

class Widget {...}:

bool operator==(const Widget& lhs. const Widgets rhs):

При вызове этой функции в контексте

if (х==у) // Предполагается, что х и у

// относятся к классу Widget

Объекту х, находящемуся слева от оператора =, в объявлении operator-= соответствует параметр Ihs, а объекту у соответствует параметр rhs.

Что касается имени класса Widget, то оно не имеет никакого отношения к графическим интерфейсам или инструментариям. Этим именем я привык обозначать «некий класс, который что-то делает». Иногда (как, например, на с. 20) имя Widget относится к шаблону класса, а не к классу. В таких случаях я продолжаю говорить о Widget как о классе несмотря на то, что в действительности это шаблон. Столь неформальное отношение к различиям между классами и шаблонами классов, структурами и шаблонами структур, функциями и шаблонами функций безвредно (при условии, что оно не приводит к возникновению неоднозначности в рассматриваемой теме). Если возможны какие-либо недоразумения, я провожу четкие различия между шаблонами и сгенерированными на их основе классами, структурами и функциями.

<p>Вопросы эффективности</p>

Сначала я хотел включить в книгу отдельную главу, посвященную вопросам эффективности, но в итоге решил, что лучше оставить привычное деление на советы. Тем не менее многие советы посвящены минимизации затрат памяти и ресурсов на стадии исполнения. Для удобства ниже приводится краткое содержание «виртуальной главы», посвященной эффективности.

Совет 4.Вызывайте empty вместо сравнения size() с нулем

Совет 5.Используйте интервальные функции вместо одноэлементных

Совет 14.Используйте reserve для предотвращения лишних операций перераспределения памяти

Совет 15.Помните о различиях в реализации string

Совет 23.Рассмотрите возможность замены ассоциативных контейнеров сортированными векторами

Совет 24.Тщательно выбирайте между map::operator[] и map::insert

Совет 25.Изучите нестандартные хэшированные контейнеры

Совет 29.Рассмотрите возможность использования istreambuf_iterator при посимвольном вводе

Совет 31.Помните о существовании разных средств сортировки

Перейти на страницу:

Все книги серии Библиотека программиста

Похожие книги