https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125299
Bug ID: 125299
Summary: Using compound requirement in default argument for
non-type template parameter fails to compile
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: deltastruct47 at gmail dot com
Target Milestone: ---
GCC fails to compile a requires-expression containing a compound requirement
when it is used directly as a default argument for a non-type template
parameter.
```
#include <concepts>
template<bool B = requires(int x){ { x } -> std::same_as<int>; }>
int i;
int main(){}
```
```
<source>:3:50: error: wrong number of template arguments (1, should be 2)
3 | template<bool B = requires(int x){ { x } -> std::same_as<int>; }>
| ^~~~~~~~~~~~
In file included from <source>:1:
/cefs/38/383ad2f84cbd57a52fd68bbe_consolidated/compilers_c++_x86_gcc_16.1.0/include/c++/16.1.0/concepts:64:13:
note: provided for 'template<class _Tp, class _Up> concept std::same_as'
64 | concept same_as
| ^~~~~~~
<source>:3:45: error: expected type-specifier
3 | template<bool B = requires(int x){ { x } -> std::same_as<int>; }>
| ^~~
<source>:3:50: error: wrong number of template arguments (1, should be 2)
3 | template<bool B = requires(int x){ { x } -> std::same_as<int>; }>
| ^~~~~~~~~~~~
/cefs/38/383ad2f84cbd57a52fd68bbe_consolidated/compilers_c++_x86_gcc_16.1.0/include/c++/16.1.0/concepts:64:13:
note: provided for 'template<class _Tp, class _Up> concept std::same_as'
64 | concept same_as
| ^~~~~~~
```
According to the C++20 standard, the form "{ E } -> Concept<Args...>;" should
be equivalent to "E; Concept<decltype((E)), Args...>;". However, in this
specific context, the compiler seems to evaluate it as "E; Concept<Args...>;"
(or similar), omitting the implicit first argument. This leads to a "wrong
number of template arguments" error.
This bug exists since GCC 12.1.0.
Workaround:
```
concept C = requires(int x){ { x } -> std::same_as<int>; };
template<bool B = C>
int a;
constexpr bool L = requires(int x){ { x } -> std::same_as<int>; };
template<bool B = L>
int b;
template<bool B = []{ return requires(int x){ { x } -> std::same_as<int>; };
}()>
int c;
```
Godbolt playground: https://godbolt.org/z/zET9sxve9