decltype спецификатор (начиная с C++11)
Определяет объявленный тип сущности или тип и категорию значения выражения.
Синтаксис
decltype ( сущность ) | (1) | |
decltype ( выражение ) | (2) |
Пояснение
| Если аргумент представляет собой непомещённое в скобки id-выражение, обозначающее структурированную привязку, то decltype возвращает ссылочный тип (описанный в спецификации объявления структурированной привязки). | (начиная с C++17) |
| Если аргумент представляет собой непомещённое в скобки id-выражение, обозначающее нетиповой параметр шаблона, то decltype возвращает тип параметра шаблона (после выполнения необходимого вывода типа, если параметр шаблона объявлен с типом-заполнителем). Тип не является const, даже если сущность представляет собой объект-параметр шаблона (который является объектом const). | (начиная с C++20) |
| Если аргумент представляет собой непомещённое в скобки выражение splice, то decltype возвращает тип сущности, объекта или значения, обозначенного этим выражением. | (начиная с C++26) |
T, иT. | Если выражение представляет собой вызов функции, возвращающий prvalue типа класса, или выражение с запятой, правый операнд которого является таким вызовом функции, для этого prvalue не создаётся временный объект. | (до C++17) |
| Если выражение является prvalue, отличным от (возможно, помещённого в скобки) немедленного вызова(начиная с C++20), из этого prvalue не материализуется временный объект: такое prvalue не имеет результирующего объекта. | (начиная с C++17) |
decltype(f(g())) g() должен иметь полный тип, а f() не обязан.Обратите внимание: если имя объекта помещено в скобки, оно рассматривается как обычное выражение 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; // type of y is double (declared type)
decltype((a->x)) z = y; // type of z is const double& (lvalue expression)
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // return type depends on template parameters
// return type can be deduced since 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*)>,
"Just returning auto isn't perfect forwarding.");
decltype(auto) getRefFwdGood(const int* p) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>,
"Returning decltype(auto) perfectly forwards the return type.");
// Alternatively:
auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>,
"Returning decltype(return expression) also perfectly forwards the return type.");
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)>,
"The type of a lambda function is unique and unnamed");
decltype(f) g = f;
std::cout << f(3, 3) << ' ' << g(3, 3) << '\n';
}
Вывод:
42 42
Ссылки
| Дополнительное содержимое |
|---|
|
См. также
auto спецификатор (C++11) | задаёт тип, выведенный из выражения |
|
(C++11) | получает ссылку на объект типа аргумента шаблона для использования в невычисляемом контексте (шаблон функции) |
|
(C++11) | проверяет, являются ли два типа одинаковыми (шаблон класса) |
|
(C++11) | получает базовый целочисленный тип для заданного типа перечисления (шаблон класса) |
Документация по C для typeof |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/decltype