Спецификатор decltype
Проверяет объявленный тип сущности или тип и категорию значения выражения.
Содержание |
[править] Синтаксис
decltype ( сущность )
|
(1) | (начиная с C++11) | |||||||
decltype ( выражение )
|
(2) | (начиная с C++11) | |||||||
[править] Объяснение
|
Если аргумент представляет собой идентификатор-выражения без скобок, именующий структурное связывание, то decltype возвращает ссылочный тип (описано в спецификации объявления структурного связывания). |
(начиная с C++17) |
|
Если аргумент представляет собой идентификатор-выражения без скобок, именующий параметр шаблона не тип, то decltype возвращает тип параметра шаблона (после выполнение любого необходимого вывода типа, если параметр шаблона объявлен с типом-заполнителем). Тип не является константным, даже если сущность является объектом параметра шаблона (который является константным объектом). |
(начиная с C++20) |
T иT&;T.
|
Если выражение является вызовом функции, которая возвращает prvalue типа класса, или является выражением запятой, правым операндом которого является такой вызов функции, временный объект для этого prvalue не вводится. |
(до C++17) |
|
Если выражение является значением prvalue отличным от (возможно, в скобках) немедленного вызова (начиная с C++20), временный объект не является материализованным из этого prvalue: такое значение prvalue не имеет объекта результата. |
(начиная с C++17) |
Обратите внимание, что если имя объекта заключено в круглые скобки, оно обрабатывается как обычное выражение lvalue, поэтому decltype(x) и decltype((x)) часто являются разными типами.
decltype полезно при объявлении типов, которые сложно или невозможно объявить с использованием стандартной нотации, например, типы, связанные с лямбда-выражениями, или типы, зависящие от параметров шаблона.
[править] Примечание
| Макрос Тестирования функциональности | Значение | Стандарт |
|---|---|---|
__cpp_decltype |
200707L | (C++11) |
[править] Ключевые слова
[править] Пример
#include <iostream> #include <type_traits> struct A { double x; }; const A* a; decltype(a->x) y; // тип y это double (объявленный тип) decltype((a->x)) z = y; // тип z это const double& (выражение lvalue) template<typename T, typename U> auto add(T t, U u) -> decltype(t + u) // возвращаемый тип зависит от параметров шаблона // тип возвращаемого значения можно вывести, // начиная с С++14 { return t + u; } const int& getRef(const int* p) { return *p; } static_assert(std::is_same_v<decltype(getRef), const int&(const int*)>); auto getRefFwdBad(const int* p) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdBad), int(const int*)>, "Простой возврат auto не является идеальной пересылкой."); decltype(auto) getRefFwdGood(const int* p) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>, "Возврат decltype(auto) идеально перенаправляет возвращаемый тип."); // Альтернатива: auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>, "Возврат decltype(выражение return) также отлично перенаправляет возвращаемый тип."); int main() { int i = 33; decltype(i) j = i * 2; std::cout << "i и j одного типа? " << std::boolalpha << std::is_same_v<decltype(i), decltype(j)> << '\n'; std::cout << "i = " << i << ", " << "j = " << j << '\n'; auto f = [](int a, int b) -> int { return a * b; }; decltype(f) g = f; // тип лямбда-функции уникален и не имеет имени i = f(2, 2); j = g(3, 3); std::cout << "i = " << i << ", " << "j = " << j << '\n'; }
Вывод:
i и j одного типа? true i = 33, j = 66 i = 4, j = 9
[править] Смотрите также
спецификатор auto (C++11)
|
специфицирует тип, полученный из выражения |
| (C++11) |
получает ссылку на свой аргумент для использования в невычисленном контексте (шаблон функции) |
| (C++11) |
проверяет, являются ли два типа одним и тем же типом (шаблон класса) |

