Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 29

Скотт Мейерс

При такой реализации f обратимся вновь к вызову, который давал нам неверную информацию о типе param при использовании typeid:

std::vector<Widget> createVec(); // Фабричная функция

const auto vw = createVec();     // Инициализация vw с помощью

                                 // фабричной функции

if (!vw.empty()) {

 f(&vw[0]);                      // Вызов f

}

После компиляции с помощью компиляторов GNU и Clang Boost.TypeIndex дает следующий (точный) результат:

Т = Widget const*

param = Widget const* const&

Применение компилятора Microsoft дает по сути то же самое:

Т = class Widget const *

param = class Widget const * const &

Такое единообразие — это хорошо, но важно помнить, что редакторы IDE, сообщения об ошибках компилятора и библиотеки наподобие Boost.TypeIndex являются всего лишь инструментами, которые можно использовать для выяснения того, какие типы выводит ваш компилятор. Это может быть полезно, но не может заменить понимания информации о выводе типов, приведенной в разделах 1.1–1.3.

Следует запомнить

• Выводимые типы часто можно просмотреть с помощью редакторов IDE, сообщений об ошибках компиляции и с использованием библиотеки Boost.TypeIndex.

• Результаты, которые выдают некоторые инструменты, могут оказаться как неточными, так и бесполезными, так что понимание правил вывода типов в С++ является совершенно необходимым.

Глава 2

Объявление auto

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

2.1. Предпочитайте auto явному объявлению типа

Легко и радостно написать

int x;

Стоп! #@$! Я забыл инициализировать x, так что эта переменная имеет неопределенное значение. Может быть. Но она может быть инициализирована и нулем — в зависимости от контекста. Жуть!

Ну, ладно. Давайте лучше порадуемся объявлению локальной переменной, инициализированной разыменованием итератора:

template<typename It> // Некий алгоритм, работающий с

void dwim(It b, It e) // элементами из диапазона от b до e

{

 while (b != e) {

  typename std::iterator_traits<It>::value_type

   currValue = *b;

 }

}

Жуть. typename std::iterator_traits<It>::value_type — просто чтобы записать тип значения, на которое указывает итератор? Нет, я такой радости не переживу… #@$! Или я это уже говорил?..