You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CWG3099 [temp.inst] Instantiation of type aliases from alias templates unspecified #782
P2996 added the idea that a type alias can result from instantiation of an alias template; however, the timing of the instantiation (and its relation to the immediate context) is unspecified.
Some thoughts:
The "traditional" expansion of alias templates are in the immediate context, but the instantiation of class and function templates are not.
Unlike classes and functions, it is not possible to declare a type alias without defining it (which may motivate "immediate" instantiation; which, in turn, reduces friction for an "immediate context" treatment).
#include<meta>usingnamespacestd::meta;template <typename T> using A = T *;
template <auto> structSink;
template <typename T> voidf(Sink<^^A<T> > * = 0); // immediately instantiated and considered as part of the immediate context?template <typename T> voidf(int = 0);
voidg() { f<int &>(); }
constexprauto x = substitute(^^A, {^^int &}); // valid until dealias?
Observations:
Implementations are performing the instantiation even when the specialization is merely named for the purposes of producing a reflection (which, in theory, only requires the identity and not the instantiation of the specialization). This extends to the case where substitute is used to form the specialization.
Implementations are treating the formation of the pointer-to-reference as being in the immediate context, which does not match the class/function template instantiation model.
I agree that it ought to be possible to form a reflection of an alias template specialization (whether through substitute or otherwise) without instantiating the underlying entity. The implemented behavior in the clang prototype is what was expedient at the time, and something that I meant to look into fixing.
If we like the suggested direction, we should make sure to gather feedback from implementers to check if there are concerns, especially since both experimental implementations separately arrived at the same (possibly undesirable) behavior.
IMO, the substitute invocation in the example should throw (and since nothing is caught, the program is ill-formed).
I consider "alias templates" to be "substituted" (which, as Hubert notes, is an immediate-context process), not "instantiated" (the process that starts a new context).
I consider "alias templates" to be "substituted" (which, as Hubert notes, is an immediate-context process), not "instantiated" (the process that starts a new context).
That is a lot more clear in a pre-P2996 world where alias templates are quite transparent. With P2996, we are supposed to have an entity (a type alias with a unique identity) associated with the reflection of each specialization of an alias template. The creation of the entity's definition sounds like "instantiation" to me.
It seems the EDG implementation on Compiler Explorer does not maintain the identity of the alias template specialization (https://godbolt.org/z/efbo8T18o):
#include<experimental/meta>usingnamespacestd::meta;template <typename T>
using A = T *;
static_assert(substitute(^^A, {^^int}) != ^^int *); // EDG rejects
I don't think there is a need to leave the immediate context here. It cannot fail once the substitution of the underlying type-id has succeeded. The type alias being created is just a convenient item to be able to query the origin of the type...
It seems the EDG implementation on Compiler Explorer does not maintain the identity of the alias template specialization (https://godbolt.org/z/efbo8T18o):
I don't think there is a need to leave the immediate context here. It cannot fail once the substitution of the underlying type-id has succeeded. The type alias being created is just a convenient item to be able to query the origin of the type...
Any other template-id that names a specialization of an alias template is a typedef-name for a type alias; such a template-id is ill-formed if forming the associated type results in substitution failure.
changed the title [-][temp.inst] Instantiation of type aliases from alias templates unspecified[/-][+]CWG3099 [temp.inst] Instantiation of type aliases from alias templates unspecified[/+]on Oct 23, 2025
There's no such thing as substitution failure in the standard.
We already use the term "substitution failure" in various places where we describe situations in which substitution is performed.
Okay, you're right. We use it mostly in notes, but I do see a reference from normative text in ([expr.prim.req.general]/5):
[...] If the substitution of template arguments into a requirement would always result in a substitution failure, the program is ill-formed; no diagnostic required.
Whoever wrote this obviously thought that "substitution failure" was a defined term. Otherwise, they would have chosen more straightforward wording, "If the substitution [...] would always fail, [...]".
Perhaps we should consider providing a definition.
Activity
katzdm commentedon Oct 20, 2025
https://github.com/bloomberg/clang-p2996/blob/63a00eeeed4c16876d989e17360b711afce08554/clang/lib/Sema/SemaReflect.cpp#L361-L362
Lol I knew this sounded familiar 🤣
katzdm commentedon Oct 20, 2025
I agree that it ought to be possible to form a reflection of an alias template specialization (whether through
substituteor otherwise) without instantiating the underlying entity. The implemented behavior in the clang prototype is what was expedient at the time, and something that I meant to look into fixing.If we like the suggested direction, we should make sure to gather feedback from implementers to check if there are concerns, especially since both experimental implementations separately arrived at the same (possibly undesirable) behavior.
daveedvdv commentedon Oct 20, 2025
IMO, the
substituteinvocation in the example should throw (and since nothing is caught, the program is ill-formed).I consider "alias templates" to be "substituted" (which, as Hubert notes, is an immediate-context process), not "instantiated" (the process that starts a new context).
hubert-reinterpretcast commentedon Oct 20, 2025
That is a lot more clear in a pre-P2996 world where alias templates are quite transparent. With P2996, we are supposed to have an entity (a type alias with a unique identity) associated with the reflection of each specialization of an alias template. The creation of the entity's definition sounds like "instantiation" to me.
hubert-reinterpretcast commentedon Oct 20, 2025
It seems the EDG implementation on Compiler Explorer does not maintain the identity of the alias template specialization (https://godbolt.org/z/efbo8T18o):
daveedvdv commentedon Oct 20, 2025
I don't think there is a need to leave the immediate context here. It cannot fail once the substitution of the underlying type-id has succeeded. The type alias being created is just a convenient item to be able to query the origin of the type...
daveedvdv commentedon Oct 20, 2025
Right. I haven't updated the EDG implementation in a loooong time. It's quite out of date wrt. the latest P2996 versions.
hubert-reinterpretcast commentedon Oct 20, 2025
If we want this direction, I think the wording change is to update https://wg21.link/temp.alias#2.sentence-2 to say:
daveedvdv commentedon Oct 20, 2025
That sounds good to me — thank you!
hubert-reinterpretcast commentedon Oct 23, 2025
@jensmaurer, as this is new from C++26, I am interested in having this addressed for plenary in Kona.
jensmaurer commentedon Oct 23, 2025
CWG3099
[-][temp.inst] Instantiation of type aliases from alias templates unspecified[/-][+]CWG3099 [temp.inst] Instantiation of type aliases from alias templates unspecified[/+]t3nsor commentedon Oct 24, 2025
There's no such thing as substitution failure in the standard. What we have is deduction failure (https://eel.is/c++draft/temp.deduct.general#8).
hubert-reinterpretcast commentedon Oct 24, 2025
We already use the term "substitution failure" in various places where we describe situations in which substitution is performed.
t3nsor commentedon Oct 25, 2025
Okay, you're right. We use it mostly in notes, but I do see a reference from normative text in ([expr.prim.req.general]/5):
Whoever wrote this obviously thought that "substitution failure" was a defined term. Otherwise, they would have chosen more straightforward wording, "If the substitution [...] would always fail, [...]".
Perhaps we should consider providing a definition.