Splicing a template name into a variable declaration using CTAD

1 day ago 4
ARTICLE AD BOX

The C++26 draft explicitly supports class template argument deduction (CTAD) where the class or alias template is designated by a splice. See [dcl.type.simple]/3:

A placeholder-type-specifier is a placeholder for a type to be deduced ([dcl.spec.auto]). A type-specifier is a placeholder for a deduced class type ([dcl.type.class.deduct]) if either

it is of the form typenameopt nested-name-specifieropt template-name or it is of the form typenameopt splice-specifier and the splice-specifier designates a class template or alias template.

The nested-name-specifier or splice-specifier, if any, shall be non-dependent and the template-name or splice-specifier shall designate a deducible template. A deducible template is either a class template or is an alias template whose defining-type-id is of the form

typenameopt nested-name-specifieropt templateopt simple-template-id

where the nested-name-specifier (if any) is non-dependent and the template-name of the simple-template-id names a deducible template. [...]

X is a class template, therefore it is a deducible template, and [:template_info:] is a splice-specifier that designates X, so it can be used as a placeholder for CTAD. Notice that this paragraph allows optional typename before the splice-specifier, but it doesn't allow template. The Clang implementation is correct.

The reason why the template disambiguator isn't allowed here is that, in general, it's needed for disambiguation only when the template name is followed by an angle bracket; for example, you sometimes need to write A<T>::template B<x> y; so that the compiler knows that the interpretation isn't the expression (A<T>::B < x) > y;. It is permitted, but deprecated, to write A<T>::template B without a following < (to my knowledge, the only place you'd do this is when using that template as a template template argument), only because prior to C++23, it had been allowed and there was some uncertainty about whether it was needed; some compilers then required it. The permission to add an unnecessary template disambiguator is not extended to newer features, like reflection.

In this particular context, the typename disambiguator also doesn't seem necessary, since you're only allowed to splice non-dependent reflections. However, it makes sense to allow it for consistency with the general case of a splice-type-specifier (i.e. a splice that designates a type), where, for usability purposes, you're allowed to put typename before it even if it's not dependent.

Read Entire Article