Эффективный и современный С++. 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
>class vector {
>public:
> …
> T& operator[](std::size_t index);
>};
>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
, например, мы указываем возвращаемый тип с использованием