https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117849
--- Comment #8 from Patrick Palka <ppalka at gcc dot gnu.org> --- (In reply to Tomasz KamiĆski from comment #7) > >> I also added a 'size(t) > 0' check and a check for a type that is not >> > >> statically sized, where the concept shouldn't become ill-formed either. > > > > FWIW I think GCC is correct to diagnose this due to > > https://eel.is/c++draft/temp.constr#atomic-3, which mandates that an atomic > > constraint after substitution yields a constant expression of type bool, > > but here it's non-constant. > > Isn't check `typename i<size(t)>;` (that is placed before) guarding the > later requires? It can only pass if size(t) is constant. Or requirements > inside require expr do not short-circuit? Good point, requirements should indeed short-circuit and so the testcase as written is well-formed. I had the first requirement commented out, which I forgot to mention :) So for sake of completeness, template <typename T> concept StaticSizedRange = requires (T &&t) { requires (size (t) > 0); }; static_assert(!StaticSizedRange<v>); is correctly diagnosed as ill-formed due to the satisfaction value being well-formed but non-constant. In order to treat non-constantness as false instead of ill-formed, we need to encode the requirement as a template argument, e.g. template <typename T> concept StaticSizedRange = requires (T &&t) { typename bool_constant<(size(t) > 0)>; }; static_assert(!StaticSizedRange<v>); which GCC incorrectly rejects. I submitted a tiny patch to fix this: https://gcc.gnu.org/pipermail/gcc-patches/2025-April/679996.html