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



>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 упрощает выражение этой зависимости. Вот пример, показывающий применение >decltype для вычисления возвращаемого типа. Этот шаблон требует уточнения, но пока что мы его отложим.

>template // Работает, но

>auto authAndAccess(Container& с, Index i)    // требует

> ->decltype(c[i])                            // уточнения

>{

> authenticateUser();

> return c[i];

>}

Использование >auto перед именем функции не имеет ничего общего с выводом типа. На самом деле оно указывает, что использован синтаксис С++11 — завершающий возвращаемый тип (trailing return type), т.е. что возвращаемый тип функции будет объявлен после списка параметров (после “>->”). Завершающий возвращаемый тип обладает тем преимуществом, что в спецификации возвращаемого типа могут использоваться параметры функции. В >authAndAccess, например, мы указываем возвращаемый тип с использованием