Please consider a concept and a class definitions: ``` template<class T> concept has_private = requires(){ &T::private_;}; class B{ int private_; friend class A; }; ``` If we first check the concept inside `A` then it will be always evaluated to true: ``` class A{ static_assert( has_private<B> ); }; static_assert( has_private<B> ); ``` Demo: https://godbolt.org/z/eYP6Tq7Y7 But if we first check the concept outside `A` then it will be always evaluated to false: ``` static_assert( !has_private<B> ); class A{ static_assert( !has_private<B> ); }; ``` Demo: https://godbolt.org/z/vsTx4oTaE Clang has the same behavior. At the same time MSVC always evaluates the concept to false, and it looks correct, because context evaluation shall not depend on the context. Related discussion: https://godbolt.org/z/vsTx4oTaE
Sorry, related discussion: https://stackoverflow.com/q/53263299/7325599
Confirmed.
> because concept-id evaluation shall not depend on the context. One consequence of making this change to concept-id evaluation would be that for: template<class T> void f() requires (!C<T>); during constraint checking for say f<int>(), we no longer evaluate C<int> (as part of evaluation of the atomic constraint !C<T>) in the access context of f, which seems surprising to me. CC'ing Jason for guidance.
GCC 11.3 is being released, retargeting bugs to GCC 11.4.
(In reply to Patrick Palka from comment #3) > > because concept-id evaluation shall not depend on the context. > > One consequence of making this change to concept-id evaluation would be that > for: > > template<class T> void f() requires (!C<T>); > > during constraint checking for say f<int>(), we no longer evaluate C<int> > (as part of evaluation of the atomic constraint !C<T>) in the access context > of f, which seems surprising to me. > > CC'ing Jason for guidance. This issue was discussed on the CWG mailing list back in 2018, but seems never to have made it to the issues list. There was general agreement at the time that access should be checked in the lexical context of the atomic constraint, as with other expressions; this does indeed have the consequence that you mention. Which means that since we don't have class-scope concepts, any constraints that need to depend on access control need to be written directly in the requires-clause rather than through a concept. Or just give up on trying to express constraints that depend on access. An alternative fix for this bug would be to include the evaluation context in the satisfaction cache.
(In reply to Jason Merrill from comment #5) > An alternative fix for this bug would be to include the evaluation context > in the satisfaction cache. ...if the evaluation involved access checking of a private or protected member.
https://cplusplus.github.io/CWG/issues/2589.html