https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124321
Bug ID: 124321
Summary: requires-expression produces hard error instead of
evaluating to false in non-dependent context
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: kachalenko.denis at gmail dot com
Target Milestone: ---
gcc -v:
gcc version 16.0.1 20260221 (experimental) (GCC)
Target: x86_64-w64-mingw32
Configured with: ../gcc-source/configure --prefix=/home/kacha/gcc-trunk-install
--build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32
--target=x86_64-w64-mingw32 --enable-languages=c,c++ --enable-threads=posix
--enable-shared --enable-static --enable-lto --enable-plugin
--enable-checking=release --disable-multilib --disable-nls --disable-werror
--disable-bootstrap --with-tune=native --with-system-zlib --with-zstd
--with-native-system-header-dir=/ucrt64/include
Reproducer:
struct S {};
static_assert(!requires(S s) { s.f(); });
int main() {}
Command:
g++ -std=c++20 test.cpp
Actual output:
test.cpp:2:34: error: 'struct S' has no member named 'f'
2 | static_assert(!requires(S s) { s.f(); });
| ^
Expected: Compilation succeeds. s.f() is ill-formed (S has no member f), so the
requires-expression evaluates to false per [expr.prim.req.general]/5, and
static_assert(!false) passes.
Workaround: The same requires-expression evaluates correctly when placed inside
a dependent context:
struct S {};
template<typename T>
constexpr bool has_f = requires(T t) { t.f(); };
static_assert(!has_f<S>);
int main() {}
This also affects constrained member functions of class templates:
template<typename T>
struct S
{
void f() requires (sizeof(T) == 1) {}
};
static_assert(!requires(S<int> s) { s.f(); }); // hard error, should pass
Reproduces with -std=c++20, -std=c++23, and -std=c++26.