[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_]