Created on 2025-08-15.00:00:00 last changed 1 month ago
Proposed resolution:
This wording is relative to N5014.
Modify [meta.reflection.substitute] as indicated:
-1- Let TARG-SPLICE(x) be:
- -1.1- template [: x :] if `is_template(x)` is `true`, otherwise
- -1.2- typename [: x :] if `is_type(x)` is `true`, otherwise
- -1.3- ([: x :])
template<reflection_range R = initializer_list<info>> consteval bool can_substitute(info templ, R&& arguments);-1- Let `Z` be the template represented by `templ` and let `Args...` be a sequence of prvalue constant expressions that compute the reflections held by the elements of `arguments`, in order.
-2- Returns: `true` if Z<TARG-SPLICE(
[:Args:])...> is a valid template-id ([temp.names]) that does not name a function whose type contains an undeduced placeholder type. Otherwise, `false`.-3- Throws: `meta::exception` unless `templ` represents a template, and every reflection in `arguments` represents a construct usable as a template argument ([temp.arg]).
-4- [Note: If forming Z<TARG-SPLICE(
[:Args:])...> leads to a failure outside of the immediate context, the program is ill-formed. — end note]template<reflection_range R = initializer_list<info>> consteval info substitute(info templ, R&& arguments);-5- Let `Z` be the template represented by `templ` and let `Args...` be a sequence of prvalue constant expressions that compute the reflections held by the elements of `arguments`, in order.
-6- Returns: Z<TARG-SPLICE(
[:Args:])...>.-7- Throws: `meta::exception` unless `can_substitute(templ, arguments)` is `true`.
-8- [Note: If forming Z<TARG-SPLICE(
[:Args:])...> leads to a failure outside of the immediate context, the program is ill-formed. — end note]
[ Kona 2025-11-08; Status changed: Immediate → WP. ]
[ Kona 2025-11-05; approved by LWG. Status changed: New → Immediate. ]
[ 2025-11-03; Tomasz provides wording. ]
[ 2025-10-27; Reflector comments. ]
We lost definition of `Z`. Use TARG-SPLICE([:Args:])....
[ 2025-10-27; Tomasz provides wording. ]
This wording is relative to N5014.
Modify [meta.reflection.substitute] as indicated:
-1- For value `x` of type `info`, and prvalue constant expression `X` that computes the reflection held by `x`, let TARG-SPLICE(x) be:
- -1.1- template [: X :] if `is_template(x)` is `true`, otherwise
- -1.2- typename [: X :] if `is_type(x)` is `true`, otherwise
- -1.3- ([: X :])
template<reflection_range R = initializer_list<info>> consteval bool can_substitute(info templ, R&& arguments);-1-
Let `Z` be the template represented by `templ` and let `Args...` be a sequence of prvalue constant expressions that compute the reflections held by the elements of `arguments`, in order.Let n be the number of elements in `arguments`, and ei be the ith element of `arguments`.-2- Returns: `true` if Z<
[:Args:]...TARG-SPLICE(e0), ..., TARG-SPLICE(en-1)> is a valid template-id ([temp.names]) that does not name a function whose type contains an undeduced placeholder type. Otherwise, `false`.-3- Throws: `meta::exception` unless `templ` represents a template, and every reflection in `arguments` represents a construct usable as a template argument ([temp.arg]).
-4- [Note: If forming Z<
[:Args:]...TARG-SPLICE(e0), ..., TARG-SPLICE(en-1)> leads to a failure outside of the immediate context, the program is ill-formed. — end note]template<reflection_range R = initializer_list<info>> consteval info substitute(info templ, R&& arguments);-5-
Let `Z` be the template represented by `templ` and let `Args...` be a sequence of prvalue constant expressions that compute the reflections held by the elements of `arguments`, in order.Let n be the number of elements in `arguments`, and ei be the ith element of `arguments`.-6- Returns: ^^Z<
[:Args:]...TARG-SPLICE(e0) ..., TARG-SPLICE(en-1)>.-7- Throws: `meta::exception` unless `can_substitute(templ, arguments)` is `true`.
-8- [Note: If forming Z<
[:Args:]...TARG-SPLICE(e0), ..., TARG-SPLICE(en-1)> leads to a failure outside of the immediate context, the program is ill-formed. — end note]
[ 2025-10-22; Reflector poll. ]
Set priority to 1 after reflector poll.
`can_substitute` and `substitute` are currently specified in terms of splices in a template argument list:
[meta.reflection.substitute] p3:Returns: `true` if Z<[:Args:]...> is a valid template-id ([temp.names]) that does not name a function whose type contains an undeduced placeholder type. Otherwise, `false`.
[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.
While the intent seems clear, this should be rephrased to be more technically correct.| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2025-11-11 10:48:55 | admin | set | messages: + msg15672 |
| 2025-11-11 10:48:55 | admin | set | status: immediate -> wp |
| 2025-11-05 21:01:40 | admin | set | messages: + msg15530 |
| 2025-11-05 21:01:40 | admin | set | status: new -> immediate |
| 2025-11-04 01:08:04 | admin | set | messages: + msg15485 |
| 2025-11-04 01:08:04 | admin | set | messages: + msg15484 |
| 2025-10-27 17:09:42 | admin | set | messages: + msg15470 |
| 2025-10-27 09:58:11 | admin | set | messages: + msg15436 |
| 2025-10-22 13:00:33 | admin | set | messages: + msg15352 |
| 2025-08-15 00:00:00 | admin | create | |