https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115614
Bug ID: 115614 Summary: Invalid (?) template substitution on variadic constrained packs Product: gcc Version: 14.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: cohenarthur at gcc dot gnu.org Target Milestone: --- GCC 14.1 rejects code that has been accepted by clang since version 15, which makes me think it should be accepted. ``` #include <stddef.h> #include <source_location> #include <type_traits> #include <utility> template <typename... Ts> struct l {}; template <typename T> struct c { using type = T; }; template <typename, size_t> concept e = true; template <size_t... i, size_t... j, size_t... k> auto subs0(std::index_sequence<i...>, std::index_sequence<j...>, std::index_sequence<k...>) { return []<e<i>... prefix, e<j>... infix, e<k>... suffix> (prefix..., infix..., suffix...) { return l<typename infix::type...>{}; }; } template <size_t a, size_t b, typename... Ts> auto subs(l<Ts...> ls) { return subs0(std::make_index_sequence<a>{}, std::make_index_sequence<b - a>{}, std::make_index_sequence<sizeof...(Ts) - b>{} )(c<Ts>{}...); } template <size_t a, size_t b, typename Ts> using sub = decltype(subs<a, b>(Ts{})); void x(sub<0, 3, l<int, int*, int**>>) {} void x(sub<0, 2, l<int, int*, int**>>) {} void x(sub<1, 2, l<int, int*, int**>>) {} void x(sub<1, 3, l<int, int*, int**>>) {} ``` clang shows no errors, whereas g++ outputs the following: ``` <source>: In instantiation of 'auto subs(l<Ts ...>) [with long unsigned int a = 0; long unsigned int b = 3; Ts = {int, int*, int**}]': <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 0; long unsigned int b = 3; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:41:36: required from here 41 | void x(sub<0, 3, l<int, int*, int**>>) {} | ^~ <source>:35:16: error: no match for call to '(subs0<, 0, 1, 2>(std::index_sequence<>, std::index_sequence<0, 1, 2>, std::index_sequence<>)::<lambda(prefix ..., infix ..., suffix ...)>) (c<int>, c<int*>, c<int**>)' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:22:10: note: candidate: 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<, 0, 1, 2>(std::index_sequence<>, std::index_sequence<0, 1, 2>, std::index_sequence<>)::<lambda(prefix ..., infix ..., suffix ...)>' 22 | return []<e<i>... prefix, | ^ <source>:22:10: note: template argument deduction/substitution failed: <source>:22:10: note: constraints not satisfied <source>: In substitution of 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<, 0, 1, 2>(std::index_sequence<>, std::index_sequence<0, 1, 2>, std::index_sequence<>)::<lambda(prefix ..., infix ..., suffix ...)> [with prefix = {}; infix = {0, 1, 2}; suffix = {}]': <source>:35:16: required from 'auto subs(l<Ts ...>) [with long unsigned int a = 0; long unsigned int b = 3; Ts = {int, int*, int**}]' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 0; long unsigned int b = 3; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:41:36: required from here 41 | void x(sub<0, 3, l<int, int*, int**>>) {} | ^~ <source>:22:10: required by the constraints of 'template<long unsigned int ...i, long unsigned int ...j, long unsigned int ...k> template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0(std::index_sequence<i ...>, std::index_sequence<j ...>, std::index_sequence<k ...>)::<lambda(prefix ..., infix ..., suffix ...)>' <source>:35:16: error: mismatched argument pack lengths while expanding 'e<infix, j>' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>: In instantiation of 'auto subs(l<Ts ...>) [with long unsigned int a = 0; long unsigned int b = 2; Ts = {int, int*, int**}]': <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 0; long unsigned int b = 2; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:42:36: required from here 42 | void x(sub<0, 2, l<int, int*, int**>>) {} | ^~ <source>:35:16: error: no match for call to '(subs0<, 0, 1, 0>(std::index_sequence<>, std::index_sequence<0, 1>, std::index_sequence<0>)::<lambda(prefix ..., infix ..., suffix ...)>) (c<int>, c<int*>, c<int**>)' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:22:10: note: candidate: 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<, 0, 1, 0>(std::index_sequence<>, std::index_sequence<0, 1>, std::index_sequence<0>)::<lambda(prefix ..., infix ..., suffix ...)>' 22 | return []<e<i>... prefix, | ^ <source>:22:10: note: template argument deduction/substitution failed: <source>:22:10: note: constraints not satisfied <source>: In substitution of 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<, 0, 1, 0>(std::index_sequence<>, std::index_sequence<0, 1>, std::index_sequence<0>)::<lambda(prefix ..., infix ..., suffix ...)> [with prefix = {}; infix = {0, 1}; suffix = {0}]': <source>:35:16: required from 'auto subs(l<Ts ...>) [with long unsigned int a = 0; long unsigned int b = 2; Ts = {int, int*, int**}]' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 0; long unsigned int b = 2; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:42:36: required from here 42 | void x(sub<0, 2, l<int, int*, int**>>) {} | ^~ <source>:22:10: required by the constraints of 'template<long unsigned int ...i, long unsigned int ...j, long unsigned int ...k> template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0(std::index_sequence<i ...>, std::index_sequence<j ...>, std::index_sequence<k ...>)::<lambda(prefix ..., infix ..., suffix ...)>' <source>:35:16: error: mismatched argument pack lengths while expanding 'e<infix, j>' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:42:6: error: redefinition of 'void x(int)' 42 | void x(sub<0, 2, l<int, int*, int**>>) {} | ^ <source>:41:6: note: 'void x(int)' previously defined here 41 | void x(sub<0, 3, l<int, int*, int**>>) {} | ^ <source>: In instantiation of 'auto subs(l<Ts ...>) [with long unsigned int a = 1; long unsigned int b = 2; Ts = {int, int*, int**}]': <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 1; long unsigned int b = 2; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:43:36: required from here 43 | void x(sub<1, 2, l<int, int*, int**>>) {} | ^~ <source>:35:16: error: no match for call to '(subs0<0, 0, 0>(std::index_sequence<0>, std::index_sequence<0>, std::index_sequence<0>)::<lambda(prefix ..., infix ..., suffix ...)>) (c<int>, c<int*>, c<int**>)' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:22:10: note: candidate: 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<0, 0, 0>(std::index_sequence<0>, std::index_sequence<0>, std::index_sequence<0>)::<lambda(prefix ..., infix ..., suffix ...)>' 22 | return []<e<i>... prefix, | ^ <source>:22:10: note: template argument deduction/substitution failed: <source>:22:10: note: constraints not satisfied <source>: In substitution of 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<0, 0, 0>(std::index_sequence<0>, std::index_sequence<0>, std::index_sequence<0>)::<lambda(prefix ..., infix ..., suffix ...)> [with prefix = {0}; infix = {0}; suffix = {0}]': <source>:35:16: required from 'auto subs(l<Ts ...>) [with long unsigned int a = 1; long unsigned int b = 2; Ts = {int, int*, int**}]' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 1; long unsigned int b = 2; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:43:36: required from here 43 | void x(sub<1, 2, l<int, int*, int**>>) {} | ^~ <source>:22:10: required by the constraints of 'template<long unsigned int ...i, long unsigned int ...j, long unsigned int ...k> template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0(std::index_sequence<i ...>, std::index_sequence<j ...>, std::index_sequence<k ...>)::<lambda(prefix ..., infix ..., suffix ...)>' <source>:35:16: error: mismatched argument pack lengths while expanding 'e<prefix, i>' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:43:6: error: redefinition of 'void x(int)' 43 | void x(sub<1, 2, l<int, int*, int**>>) {} | ^ <source>:41:6: note: 'void x(int)' previously defined here 41 | void x(sub<0, 3, l<int, int*, int**>>) {} | ^ <source>: In instantiation of 'auto subs(l<Ts ...>) [with long unsigned int a = 1; long unsigned int b = 3; Ts = {int, int*, int**}]': <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 1; long unsigned int b = 3; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:44:36: required from here 44 | void x(sub<1, 3, l<int, int*, int**>>) {} | ^~ <source>:35:16: error: no match for call to '(subs0<0, 0, 1>(std::index_sequence<0>, std::index_sequence<0, 1>, std::index_sequence<>)::<lambda(prefix ..., infix ..., suffix ...)>) (c<int>, c<int*>, c<int**>)' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:22:10: note: candidate: 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<0, 0, 1>(std::index_sequence<0>, std::index_sequence<0, 1>, std::index_sequence<>)::<lambda(prefix ..., infix ..., suffix ...)>' 22 | return []<e<i>... prefix, | ^ <source>:22:10: note: template argument deduction/substitution failed: <source>:22:10: note: constraints not satisfied <source>: In substitution of 'template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0<0, 0, 1>(std::index_sequence<0>, std::index_sequence<0, 1>, std::index_sequence<>)::<lambda(prefix ..., infix ..., suffix ...)> [with prefix = {0}; infix = {0, 1}; suffix = {}]': <source>:35:16: required from 'auto subs(l<Ts ...>) [with long unsigned int a = 1; long unsigned int b = 3; Ts = {int, int*, int**}]' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:39:32: required by substitution of 'template<long unsigned int a, long unsigned int b, class Ts> using sub = decltype (subs<a, b>(Ts{})) [with long unsigned int a = 1; long unsigned int b = 3; Ts = l<int, int*, int**>]' 39 | using sub = decltype(subs<a, b>(Ts{})); | ~~~~~~~~~~^~~~~~ <source>:44:36: required from here 44 | void x(sub<1, 3, l<int, int*, int**>>) {} | ^~ <source>:22:10: required by the constraints of 'template<long unsigned int ...i, long unsigned int ...j, long unsigned int ...k> template<class ... prefix, class ... infix, class ... suffix> requires ((... && e<prefix, i>)) && ((... && e<infix, j>)) && ((... && e<suffix, k>)) subs0(std::index_sequence<i ...>, std::index_sequence<j ...>, std::index_sequence<k ...>)::<lambda(prefix ..., infix ..., suffix ...)>' <source>:35:16: error: mismatched argument pack lengths while expanding 'e<prefix, i>' 32 | return subs0(std::make_index_sequence<a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | std::make_index_sequence<b - a>{}, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | std::make_index_sequence<sizeof...(Ts) - b>{} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | )(c<Ts>{}...); | ~^~~~~~~~~~~~ <source>:44:6: error: redefinition of 'void x(int)' 44 | void x(sub<1, 3, l<int, int*, int**>>) {} | ^ <source>:41:6: note: 'void x(int)' previously defined here 41 | void x(sub<0, 3, l<int, int*, int**>>) {} | ^ Compiler returned: 1 ``` CE link for a quick comparison between GCC 14.1 and clang 15: https://godbolt.org/z/YGfq5bG44