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



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

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

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

>int x;

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

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

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

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

>{

> while (b != e) {

>  typename std::iterator_traits::value_type

>   currValue = *b;

> }

>}

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

Ладно, третья попытка. Попробую объявить локальную переменную, тип которой такой же, как у лямбда-выражения. Но его тип известен только компилятору. #@$! (Это становится привычкой…)

Да что же это такое — никакого удовольствия от программирования на С++! Так не должно быть. И не будет! Мы дождались С++11, в котором все эти проблемы решены с помощью ключевого слова >auto. Тип переменных, объявленных как >auto, выводится из их инициализатора, так что они обязаны быть инициализированными. Это значит — прощай проблема неинициализированных переменных:

>int x1;      // Потенциально неинициализированная переменная

>auto x2;     // Ошибка! Требуется инициализатор

>auto x3 = 0; // Все отлично, переменная x корректно определена

Нет проблем и с объявлением локальной переменной, значением которой является разыменование итератора:

>template // Все, как и ранее

>void dwim(It b, It e) {

> while (b != e) {

>  auto currValue = *b;

> }

>}

А поскольку >auto использует вывод типов (см. раздел 1.2), он может представлять типы, известные только компиляторам:

>auto derefUPLess =                     // Функция сравнения

> [](const std::unique_ptr& p1, // объектов Widget, на

>    const std::unique_ptr& p2) // которые указывают

>    { return *p1 < *p2; );             // std::unique_ptr

Просто круто! В С++14 все еще круче, потому что параметры лямбда-выражений также могут включать