Оператор decltype
Проверяет объявленный тип сущности или тип и категорию значения выражения.
Синтаксис
decltype ( сущность ) | (1) | (с C++11) |
decltype ( выражение ) | (2) | (с C++11) |
Описание
| Если аргумент — это выражение id-выражение без скобок, называющее структурированное связывание, то decltype возвращает ссылочный тип (описанный в спецификации объявления структурированного связывания). | (с C++17) |
| Если аргумент — это выражение id-выражение без скобок, называющее параметр шаблона нетипового типа, то decltype возвращает тип параметра шаблона (после выполнения любого необходимого вывода типа, если параметр шаблона объявлен с типом-заполнителем). Тип не является константным, даже если сущность — объект параметра шаблона (который является константным объектом). | (с C++20) |
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 документация для typeof |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/decltype