9 Declarations [dcl]

9.2 Specifiers [dcl.spec]

9.2.9 Type specifiers [dcl.type]

9.2.9.6 Decltype specifiers [dcl.type.decltype]

For an expression E, the type denoted by decltype(E) is defined as follows:
  • if E is an unparenthesized id-expression naming a structured binding ([dcl.struct.bind]), decltype(E) is the referenced type as given in the specification of the structured binding declaration;
  • otherwise, if E is an unparenthesized id-expression naming a constant template parameter ([temp.param]), decltype(E) is the type of the template parameter after performing any necessary type deduction ([dcl.spec.auto], [dcl.type.class.deduct]);
  • otherwise, if E is an unparenthesized id-expression or an unparenthesized class member access ([expr.ref]), decltype(E) is the type of the entity named by E.
    If there is no such entity, the program is ill-formed;
  • otherwise, if E is an unparenthesized splice-expression, decltype(E) is the type of the entity, object, or value designated by the splice-specifier of E;
  • otherwise, if E is an xvalue, decltype(E) is T&&, where T is the type of E;
  • otherwise, if E is an lvalue, decltype(E) is T&, where T is the type of E;
  • otherwise, decltype(E) is the type of E.
The operand of the decltype specifier is an unevaluated operand.
[Example 1: const int& foo(); int i; struct A { double x; }; const A* a = new A(); decltype(foo() x1 = 17; / type is const int&& decltype(i) x2; / type is int decltype(a->x) x3; / type is double decltype(a->x)) x4 = x3; / type is const double& decltype([:^x1:]) x5 = 18; / type is const int&& decltype([:^x1:]) x6 = 19; / type is const int& void f() { [](auto ..pack) { decltype(pack..[0]) x7; / type is int decltype(pack..[0]) x8; / type is int& }(0); } — end example]
[Note 1: 
The rules for determining types involving decltype(auto) are specified in [dcl.spec.auto].
— end note]
If the operand of a decltype-specifier is a prvalue and is not a (possibly parenthesized) immediate invocation ([expr.const]), the temporary materialization conversion is not applied ([conv.rval]) and no result object is provided for the prvalue.
The type of the prvalue may be incomplete or an abstract class type.
[Note 2: 
As a result, storage is not allocated for the prvalue and it is not destroyed.
Thus, a class type is not instantiated as a result of being the type of a function call in this context.
In this context, the common purpose of writing the expression is merely to refer to its type.
In that sense, a decltype-specifier is analogous to a use of a typedef-name, so the usual reasons for requiring a complete type do not apply.
In particular, it is not necessary to allocate storage for a temporary object or to enforce the semantic constraints associated with invoking the type's destructor.
— end note]
[Note 3: 
Unlike the preceding rule, parentheses have no special meaning in this context.
— end note]
[Example 2: template<class T> struct A { ~A() = delete; }; template<class T> auto h() -> A<T>; template<class T> auto i(T) / identity -> T; template<class T> auto f(T) / #1 -> decltype(i(h<T>(); / forces completion of A<T> and implicitly uses A<T>​::​~A() / for the temporary introduced by the use of h(). / (A temporary is not introduced as a result of the use of i().) template<class T> auto f(T) / #2 -> void; auto g() -> void { f(42); / OK, calls #2. (#1 is not a viable candidate: type deduction / fails ([temp.deduct]) because A<int>​::​~A() is implicitly used in its / decltype-specifier) } template<class T> auto q(T) -> decltype(h<T>(); / does not force completion of A<T>; A<T>​::​~A() is not implicitly / used within the context of this decltype-specifier void r() { q(42); / error: deduction against q succeeds, so overload resolution selects / the specialization “q(T) -> decltype((h<T>()))'' with T / the return type is A<int>, so a temporary is introduced and its / destructor is used, so the program is ill-formed } — end example]

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant