Перейти к содержанию

Последнее обновление:2026-10-12

C++ выведение типов с decltype

Об авторе:

Личный официальный аккаунт:

wechat

1.Основное использование

Синтаксис decltype таков:

decltype (expression)

Скобки здесь обязательны; роль decltype — «запросить тип выражения», поэтому приведённый выше оператор возвращает тип выражения expression. Обратите внимание: decltype лишь «запрашивает» тип выражения и не «вычисляет» само выражение.

1.1 Выведение типа выражения

int i = 4;
decltype(i) a; //推导结果为int。a的类型为int。

1.2 Использование вместе с using/typedef для определения типов.

using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型
using ptrdiff_t = decltype((int*)0 - (int*)0);
using nullptr_t = decltype(nullptr);
vector<int >vec;
typedef decltype(vec.begin()) vectype;
for (vectype i = vec.begin; i != vec.end(); i++)
{
//...
}

Так же, как и auto, это повышает читаемость кода.

1.3 Повторное использование анонимных типов

В C++ мы иногда сталкиваемся с анонимными типами, например:

struct 
{
    int d ;
    double b;
}anon_s;

А с помощью decltype мы можем повторно использовать эту анонимную структуру:

decltype(anon_s) as ;//定义了一个上面匿名的结构体

1.4 В сочетании с auto в обобщённом программировании — для отслеживания типа возвращаемого значения функции

Это самое главное применение decltype.

template <typename T>
auto multiply(T x, T y)->decltype(x*y)
{
    return x*y;
}

Полный код см. в: decltype.cpp

2.Правила определения

Для decltype(e) результат определения зависит от следующих условий:

Если e — выражение-идентификатор без скобок или выражение доступа к члену класса, то decltype(e) — это тип сущности, названной через e. Кроме того, если e — перегруженная функция, это приведёт к ошибке компиляции. Иначе, пусть тип e — T: если e — xvalue (будущее значение), то decltype(e) будет T&&. Иначе, пусть тип e — T: если e — lvalue (левостороннее значение), то decltype(e) будет T&. Иначе, пусть тип e — T: тогда decltype(e) будет T.

Идентификатор — это определённый программистом токен, за исключением ключевых слов, литералов и других токенов, которые нужны компилятору; выражение, соответствующее одиночному идентификатору, называется выражением-идентификатором. Например:

int arr[4]
тогда arr — выражение-идентификатор, а arr[3]+0 — нет.

Примеры:

int i = 4;
int arr[5] = { 0 };
int *ptr = arr;
struct S{ double d; }s ;
void Overloaded(int);
void Overloaded(char);//重载的函数
int && RvalRef();
const bool Func(int);

//规则一:推导为其类型
decltype (arr) var1; //int[] 标记符表达式

decltype (ptr) var2;//int *  标记符表达式

decltype(s.d) var3;//doubel 成员访问表达式

//decltype(Overloaded) var4;//重载函数。编译错误。

//规则二:将亡值。推导为类型的右值引用。

decltype (RvalRef()) var5 = 1;

//规则三:左值,推导为类型的引用。

decltype ((i))var6 = i;     //int&

decltype (true ? i : i) var7 = i; //int&  条件表达式返回左值。

decltype (++i) var8 = i; //int&  ++i返回i的左值。

decltype(arr[5]) var9 = i;//int&. []操作返回左值

decltype(*ptr)var10 = i;//int& *操作返回左值

decltype("hello")var11 = "hello"; //const char(&)[9]  字符串字面常量为左值,且为const左值。


//规则四:以上都不是,则推导为本类型

decltype(1) var12;//const int

decltype(Func(1)) var13=true;//const bool

decltype(i++) var14 = i;//int i++返回右值

Учебный материал: https://www.cnblogs.com/QG-whz/p/4952980.html

Похожие темы

Комментарии