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

Шрифт
Интервал

для некоторого неизвестного , вывод типа шаблона сможет определить, чем является :

>template

>void f(std::initializer_list<T> initList);


>f({ 11, 23, 9 }); // Вывод int в качестве типа Т, а тип

>                  // initList - std::initializer_list

Таким образом, единственное реальное различие между выводом типа >auto и выводом типа шаблона заключается в том, что >autoпредполагает, что инициализатор в фигурных скобках представляет собой >std::initializer_list, в то время как вывод типа шаблона этого не делает.

Вы можете удивиться, почему вывод типа >auto имеет специальное правило для инициализаторов в фигурных скобках, в то время как вывод типа шаблона такого правила не имеет. Но я и сам удивлен. Увы, я не в состоянии найти убедительное объяснение. Но “закон есть закон”, и это означает, что вы должны помнить, что если вы объявляете переменную с использованием ключевого слова >auto и инициализируете ее с помощью инициализатора в фигурных скобках, то выводимым типом всегда будет >std::initializer_list. Особенно важно иметь это в виду, если вы приверженец философии унифицированной инициализации — заключения инициализирующих значений в фигурные скобки как само собой разумеющегося стиля. Классической ошибкой в С++11 является случайное объявление переменной >std::initializer_list там, где вы намеревались объявить нечто иное. Эта ловушка является одной из причин, по которым некоторые разработчики используют фигурные скобки в инициализаторах только тогда, когда обязаны это делать. (Когда именно вы обязаны так поступать, мы рассмотрим в разделе 3.1.)

Что касается С++ 11, то на этом история заканчивается, но для С++14 это еще не конец. С++14 допускает применение >auto для указания того, что возвращаемый тип функции должен быть выведен (см. раздел 1.3), а кроме того, лямбда-выражения С++ 14 могут использовать >auto в объявлениях параметров. Однако такое применение >auto использует вывод типа шаблона, а не вывод типа >auto. Таким образом, функция с возвращаемым типом >auto, которая возвращает инициализатор в фигурных скобках, компилироваться не будет:

>auto createInitList() {

> return { 1, 2, 3 }; // Ошибка: невозможно вывести

>}                    // тип для { 1, 2, 3 }

То же самое справедливо и тогда, когда >auto используется в спецификации типа параметра в лямбда-выражении С++14:

>std::vector v;


>auto resetV =

> [&v](const auto& newValue) { v = newValue; }; // C++14


>resetV({ 1, 2, 3 }); // Ошибка: невозможно вывести

>                     // тип для { 1, 2, 3 }

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

• Вывод типа >auto обычно такой же, как и вывод типа шаблона, но вывод типа >auto, в отличие от вывода типа шаблона, предполагает, что инициализатор в фигурных скобках представляет >std::initializer_list.

• >auto в возвращаемом типе функции или параметре лямбда-выражения влечет применение вывода типа шаблона, а не вывода типа >auto.

1.3. Знакомство с >decltype

>decltype — создание странное. Для данного имени или выражения >decltype сообщает вам тип этого имени или выражения. Обычно то, что сообщает >decltype, — это именно то, что вы предсказываете. Однако иногда он дает результаты, которые заставляют вас чесать в затылке и обращаться к справочникам или сайтам.

Мы начнем с типичных случаев, в которых нет никаких подводных камней. В отличие от того, что происходит в процессе вывода типов для шаблонов и >auto (см. разделы 1.1 и 1.2), >decltype обычно попугайничает, возвращая точный тип имени или выражения, которое вы передаете ему:

>const int i = 0;         // decltype(i) - const int


>bool f(const Widget& w); // decltype(w) - const Widget&

>                         // decltype(f) - bool(const Widget&)


>struct Point {

> int x, y;               // decltype (Point::x) - int

>};                       // decltype(Point::y) – int


>Widget w;                // decltype(w) – Widget


>if (f(w)) …              // decltype (f(w)) — bool


>template     // Упрощенная версия std::vector

>class vector {

>public:

> …

> T& operator[](std::size_t index);

>};


>vector v;           // decltype(v) – vector

>…

>if (v[0] == 0) …                  >// decltype(v[0]) - int&

Видите? Никаких сюрпризов.

Пожалуй, основное применение >decltype в С++11 — объявление шаблонов функций, в которых возвращаемый тип функции зависит от типов ее параметров. Предположим, например, что мы хотим написать функцию, получающую контейнер, который поддерживает индексацию с помощью квадратных скобок (т.е. с использованием “>[]”) с индексом, а затем аутентифицирует пользователя перед тем как вернуть результат операции индексации. Возвращаемый тип функции должен быть тем же, что и тип, возвращаемый операцией индексации.

>operator[] для контейнера объектов типа обычно возвращает >Т&. Например, это так в случае >std::deque и почти всегда — в случае >std::vector. Однако для >std::vector оператор >operator[] не возвращает >bool&. Вместо этого он возвращает новый объект. Все “почему” и “как” данной ситуации рассматриваются в разделе 2.2, но главное здесь то, что возвращаемый оператором >operator[] контейнера тип зависит от самого контейнера.

>decltype упрощает выражение этой зависимости. Вот пример, показывающий применение


Еще от автора Скотт Мейерс
Эффективное использование STL

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


Как функции, не являющиеся методами, улучшают инкапсуляцию

Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Виртуальная библиотека Delphi

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка баз данных на Visual Basic.NET

Это практическое руководство разработчика программного обеспечения на Visual Basic .NET и ADO.NET, предназначенное для создания приложений баз данных на основе WinForms, Web-форм и Web-служб. В книге описываются практические способы решения задач доступа к данным, с которыми сталкиваются разработчики на Visual Basic .NET в своей повседневной деятельности. Книга начинается с основных сведений о создании баз данных, использовании языка структурированных запросов SQL и системы управления базами данных Microsoft SQL Server 2000.


Исчерпывающее руководство по написанию всплывающих подсказок

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Программное обеспечение встроенных систем. Общие требования к разработке и документированию

Embedded system software. General requirements for development and documentationСтандарт подготовлен в развитие ГОСТ Р ИСО/МЭК 12207-99 «Информационная технология. Процессы жизненного цикла программных средств» с целью учета специфики разработки и документирования программного обеспечения встроенных систем реального времени.


Как пасти котов. Наставление для программистов, руководящих другими программистами

«Как пасти котов» – это книга о лидерстве и руководстве, о том, как первое совмещать со вторым. Это, если хотите, словарь трудных случаев управления IT-проектами. Программист подобен кошке, которая гуляет сама по себе. Так уж исторически сложилось. Именно поэтому так непросто быть руководителем команды разработчиков. Даже если вы еще месяц назад были блестящим и дисциплинированным программистом и вдруг оказались в роли менеджера, вряд ли вы знаете, с чего надо начать, какой выбрать стиль руководства, как нанимать и увольнять сотрудников, проводить совещания, добиваться своевременного выполнения задач.