[dcl.type.decltype] (original) (raw)
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, adecltype-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) -> T;template<class T> auto f(T) -> decltype(i(h<T>())); template<class T> auto f(T) -> void;auto g() -> void { f(42); } template<class T> auto q(T) -> decltype((h<T>())); void r() { q(42); } — _end example_]