21 Metaprogramming library [meta]

21.4 Reflection [meta.reflection]

21.4.12 Reflection substitution [meta.reflection.substitute]

template<class R> concept reflection_range = ranges::input_range<R> && same_as<ranges::range_value_t<R>, info> && same_as<remove_cvref_t<ranges::range_reference_t<R>>, info>; template<reflection_range R = initializer_list<info>> consteval bool can_substitute(info templ, R&& arguments);
Constant When: templ represents a template, and every reflection in arguments represents a construct usable as a template argument ([temp.arg]).
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.
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.
[Note 1: 
If forming Z<[: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);
Constant When: can_substitute(templ, arguments) is true.
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.
Returns: ^^Z<[:Args:]...>.
[Note 2: 
If forming Z<[:Args:]...> leads to a failure outside of the immedaite context, the program is ill-formed.
— end note]
[Example 1: template<class T> auto fn1(); static_assert(!can_substitute(^^fn1, {^^int})); // OK constexpr info r1 = substitute(^^fn1, {^^int}); // error: fn<int> contains an undeduced // placeholder type template<class T> auto fn2() { static_assert(^^T != ^^int); // static assertion failed during instantiation of fn<int> return 0; } constexpr bool r2 = can_substitute(^^fn2, {^^int}); // error: instantiation of body of fn<int> // is needed to deduce return type — end example]
[Example 2: consteval info to_integral_constant(unsigned i) { return substitute(^^integral_constant, {^^unsigned, reflect_constant(i)}); } constexpr info r = to_integral_constant(2); // OK, r represents the type // integral_constant<unsigned, 2> — end example]