decltype
specifier
(since C++11)
Проверяет объявленный тип сущности или тип и категорию значения выражения.
Содержание |
Синтаксис
decltype (
entity
)
|
(1) | ||||||||
decltype (
expression
)
|
(2) | ||||||||
Объяснение
|
Если аргумент представляет собой не заключённое в скобки id-выражение , именующее структурированную привязку , то decltype возвращает ссылочный тип (описанный в спецификации объявления структурированной привязки). |
(since C++17) |
|
Если аргумент представляет собой не заключённое в скобки id-выражение , именующее постоянный параметр шаблона , то decltype возвращает тип параметра шаблона (после выполнения любого необходимого вывода типа, если параметр шаблона объявлен с типом-заполнителем). Тип является не-const, даже если сущность является объектом параметра шаблона (который является const-объектом). |
(since C++20) |
T
, и
|
Если выражение является вызовом функции, возвращающим prvalue классового типа, или выражением с запятой , чей правый операнд является таким вызовом функции, временный объект не создаётся для этого prvalue. |
(до C++17) |
|
Если выражение является prvalue , кроме (возможно, в круглых скобках) немедленного вызова (начиная с C++20) , временный объект не материализуется из этого prvalue: такой prvalue не имеет объекта результата. |
(начиная с C++17) |
Обратите внимание, что если имя объекта заключено в круглые скобки, оно трактуется как обычное lvalue-выражение, поэтому decltype ( x ) и decltype ( ( x ) ) часто являются разными типами.
decltype
полезен при объявлении типов, которые сложно или невозможно объявить с использованием стандартной нотации, например типов, связанных с лямбда-выражениями, или типов, зависящих от параметров шаблонов.
Примечания
| Макрос тестирования возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_decltype
|
200707L
|
(C++11) | decltype |
Ключевые слова
Пример
#include <cassert> #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) // возвращаемый тип зависит от параметров шаблона // возвращаемый тип может быть выведен начиная с C++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(выражение возврата) также идеально пересылает возвращаемый тип."); int main() { int i = 33; decltype(i) j = i * 2; static_assert(std::is_same_v<decltype(i), decltype(j)>); assert(i == 33 && 66 == j); auto f = [i](int av, int bv) -> int { return av * bv + i; }; auto h = [i](int av, int bv) -> int { return av * bv + i; }; static_assert(!std::is_same_v<decltype(f), decltype(h)>, "Тип лямбда-функции уникален и не имеет имени"); decltype(f) g = f; std::cout << f(3, 3) << ' ' << g(3, 3) << '\n'; }
Вывод:
42 42
Ссылки
| Расширенное содержимое |
|---|
|
|
Этот раздел не завершён
Причина: Требует исправления. См.: Talk: Wrong References . |
Смотрите также
auto
спецификатор
(C++11)
|
указывает тип, выводимый из выражения |
|
(C++11)
|
получает ссылку на объект шаблонного типа аргумента для использования в невычисляемом контексте
(шаблон функции) |
|
(C++11)
|
проверяет, являются ли два типа одинаковыми
(шаблон класса) |
|
Документация C
для
typeof
|
|