I haven't been able to find a good explanation of decltype. Please tell me, as a beginning programmer, what it does and why it is useful.
For example, I am reading a book that asked the following question:
What would be the type of each variable and what value would each variable have when the code finishes?
int a = 3, b = 4; decltype(a) c = a; decltype((b)) d = a; ++c; ++d;
Can someone explain to me the answer and why, along with some good (beginner-level) examples? A line-by-line explanation would be very helpful.
decltype
is a way to specify a type: You give it an expression, and decltype
gives you back a type which corresponds to the type of the expression, as explained in [dcl.type.simple] p4:
The type denoted by
decltype(e)
is defined as follows:
- if
e
is an unparenthesized id-expression or an unparenthesized class member access ([expr.ref]),decltype(e)
is the type of the entity named bye
. If there is no such entity, or ife
names a set of overloaded functions, the program is ill-formed;- otherwise, if
e
is an xvalue,decltype(e)
isT&&
, whereT
is the type ofe
;- otherwise, if
e
is an lvalue,decltype(e)
isT&
, whereT
is the type ofe
;- otherwise,
decltype(e)
is the type ofe
.
Note that the first bullet covers decltype(a)
, and the subsequent bullets cover double parentheses cases like decltype((b))
.
Combining these rules with reference collapsing rules allows you to make sense of decltype(e) &&
, which is always a "suitable" reference. (C++14 also adds decltype(auto)
to give you the type-deduction of auto
combined with the value category semantics of decltype
.)
int foo();
int n = 10;
decltype(n) a = 20; // a is an "int" [unparenthesized id-expression]
decltype((n)) b = a; // b is an "int &" [(n) is an lvalue]
decltype((std::move(n))) c = a; // c is an "int &&" [(std::move(n)) is an xvalue]
decltype(foo()) d = foo(); // d is an "int" [(foo()) is a prvalue]
decltype(foo()) && r1 = foo(); // int &&
decltype((n)) && r2 = n; // int & [& && collapses to &]
It might be worth stressing the difference between auto
and decltype
: auto
works on types, and decltype
works on expressions.
You shouldn't be seeing or using decltype
in "day-to-day" programming. It is most useful in generic (templated) library code, where the expression in question is not known and depends on a parameter. (By contrast, auto
may be used generously all over the place.) In short, if you're new to programming, you probably won't need to use decltype
for some time.