public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/115614] New: Invalid (?) template substitution on variadic constrained packs
@ 2024-06-24 10:27 cohenarthur at gcc dot gnu.org
  0 siblings, 0 replies; only message in thread
From: cohenarthur at gcc dot gnu.org @ 2024-06-24 10:27 UTC (permalink / raw)
  To: gcc-bugs

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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-06-24 10:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-24 10:27 [Bug c++/115614] New: Invalid (?) template substitution on variadic constrained packs cohenarthur at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).