Skip to content

Last updated:2026-10-12

C++ decltype Type Deduction

About the Author

WeChat official account:

wechat

1. Basic Usage

The syntax of decltype is:

decltype (expression)

The parentheses here are indispensable. decltype's job is to "query the type of an expression", so the statement above has the effect of returning the type of the expression. Note that decltype merely "queries" the type of the expression; it does not "evaluate" the expression.

1.1 Deduce the Type of an Expression

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

1.2 Used Together with using/typedef to Define Types

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++)
{
//...
}

Like auto, this also improves the readability of the code.

1.3 Reusing Anonymous Types

In C++, we sometimes come across anonymous types, such as:

struct 
{
    int d ;
    double b;
}anon_s;

And with the help of decltype, we can reuse this anonymous struct:

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

1.4 Combined with auto in Generic Programming to Track a Function's Return Type

This is also the biggest use of decltype.

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

See the complete code at: decltype.cpp

2. Deduction Rules

For decltype(e), the deduction result is affected by the following conditions:

If e is an unparenthesized id-expression or a class member access expression, then decltype(e) is the type of the entity named by e. In addition, if e is an overloaded function, this causes a compile error. Otherwise, suppose the type of e is T; if e is an xvalue, then decltype(e) is T&&. Otherwise, suppose the type of e is T; if e is an lvalue, then decltype(e) is T&. Otherwise, suppose the type of e is T; then decltype(e) is T.

An identifier refers to a token defined by the programmer, excluding keywords, literals, and other tokens the compiler needs; the expression corresponding to a single identifier is an id-expression. For example:

int arr[4]
Here arr is an id-expression, while arr[3]+0 is not.

For example:

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++返回右值

Learning reference: https://www.cnblogs.com/QG-whz/p/4952980.html

Comments