Читать «Эффективный и современный С++. 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
— просто чтобы записать тип значения, на которое указывает итератор? Нет, я такой радости не переживу… #@$! Или я это уже говорил?..