This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.
{can_}substitute specification is ill-formedSection: 21.4.13 [meta.reflection.substitute] Status: WP Submitter: Matthias Wippich Opened: 2025-08-15 Last modified: 2025-11-11
Priority: 1
View all issues with WP status.
Discussion:
Addresses US 114-175
can_substitute and substitute are currently specified in terms of splices in a template argument list:
Returns:
trueifZ<[:Args:]...>is a valid template-id (13.3 [temp.names]) that does not name a function whose type contains an undeduced placeholder type. Otherwise,false.
21.4.13 [meta.reflection.substitute] p7:
Returns:
^^Z<[:Args:]...>.
This wording was introduced in P2996R11. However, merging in changes from
P3687 "Final Adjustments to C++26 Reflection" in P2996R13 changed
the rules for splices in this context. This makes can_substitute and substitute as specified
currently ill-formed. We cannot use the given syntax to splice an arbitrary choice of values,
types and templates anymore.
[2025-10-22; Reflector poll.]
Set priority to 1 after reflector poll.
[2025-10-27; Tomasz provides wording.]
Previous resolution [SUPERSEDED]:
This wording is relative to N5014.
Modify 21.4.13 [meta.reflection.substitute] as indicated:
-1- For value
xof typeinfo, and prvalue constant expressionXthat computes the reflection held byx, letTARG-SPLICE(x)be:
- -1.1-
template [: X :]ifis_template(x)istrue, otherwise- -1.2-
typename [: X :]ifis_type(x)istrue, otherwise- -1.3-
([: X :])template<reflection_range R = initializer_list<info>> consteval bool can_substitute(info templ, R&& arguments);-1-
LetLet n be the number of elements inZbe the template represented bytempland letArgs...be a sequence of prvalue constant expressions that compute the reflections held by the elements ofarguments, in order.arguments, and ei be the ith element ofarguments.-2- Returns:
trueifZ<is a valid template-id (13.3 [temp.names]) that does not name a function whose type contains an undeduced placeholder type. Otherwise,[:Args:]...TARG-SPLICE(e0), ..., TARG-SPLICE(en-1)>false.-3- Throws:
meta::exceptionunlesstemplrepresents a template, and every reflection inargumentsrepresents a construct usable as a template argument (13.4 [temp.arg]).-4- [Note: If forming
Z<leads to a failure outside of the immediate context, the program is ill-formed. — end note][:Args:]...TARG-SPLICE(e0), ..., TARG-SPLICE(en-1)>template<reflection_range R = initializer_list<info>> consteval info substitute(info templ, R&& arguments);-5-
LetLet n be the number of elements inZbe the template represented bytempland letArgs...be a sequence of prvalue constant expressions that compute the reflections held by the elements ofarguments, in order.arguments, and ei be the ith element ofarguments.-6- Returns:
^^Z<.[:Args:]...TARG-SPLICE(e0) ..., TARG-SPLICE(en-1)>-7- Throws:
meta::exceptionunlesscan_substitute(templ, arguments)istrue.-8- [Note: If forming
Z<leads to a failure outside of the immediate context, the program is ill-formed. — end note][:Args:]...TARG-SPLICE(e0), ..., TARG-SPLICE(en-1)>
[2025-10-27; Reflector comments.]
We lost definition of Z. Use TARG-SPLICE([:Args:])....
[2025-11-03; Tomasz provides wording.]
[Kona 2025-11-05; approved by LWG. Status changed: New → Immediate.]
[Kona 2025-11-08; Status changed: Immediate → WP.]
Proposed resolution:
This wording is relative to N5014.
Modify 21.4.13 [meta.reflection.substitute] as indicated:
-1- Let
TARG-SPLICE(x)be:
- -1.1-
template [: x :]ifis_template(x)istrue, otherwise- -1.2-
typename [: x :]ifis_type(x)istrue, otherwise- -1.3-
([: x :])template<reflection_range R = initializer_list<info>> consteval bool can_substitute(info templ, R&& arguments);-1- Let
Zbe the template represented bytempland letArgs...be a sequence of prvalue constant expressions that compute the reflections held by the elements ofarguments, in order.-2- Returns:
trueifZ<TARG-SPLICE(is a valid template-id (13.3 [temp.names]) that does not name a function whose type contains an undeduced placeholder type. Otherwise,[:Args:])...>false.-3- Throws:
meta::exceptionunlesstemplrepresents a template, and every reflection inargumentsrepresents a construct usable as a template argument (13.4 [temp.arg]).-4- [Note: If forming
Z<TARG-SPLICE(leads to a failure outside of the immediate context, the program is ill-formed. — end note][:Args:])...>template<reflection_range R = initializer_list<info>> consteval info substitute(info templ, R&& arguments);-5- Let
Zbe the template represented bytempland letArgs...be a sequence of prvalue constant expressions that compute the reflections held by the elements ofarguments, in order.-6- Returns:
Z<TARG-SPLICE(.[:Args:])...>-7- Throws:
meta::exceptionunlesscan_substitute(templ, arguments)istrue.-8- [Note: If forming
Z<TARG-SPLICE(leads to a failure outside of the immediate context, the program is ill-formed. — end note][:Args:])...>