https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67070
Jason Merrill <jason at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2015-07-31 Ever confirmed|0 |1 --- Comment #1 from Jason Merrill <jason at gcc dot gnu.org> --- This issue is another consequence of my earlier observation about the ! operator, that it produces a single predicate. Reduced: template <class T> concept bool A = requires { typename T::Type; } && T::Type::value; template <class T> requires !A<T> void f() { } struct B { }; int main() { f<B>(); } Here f has a single atomic predicate constraint, !(requires { typename T::Type } && T::Type::value) Substitution into this constraint fails because B has no member Type, and template argument substitution doesn't stop after substituting into the requires-expression. Since argument substitution fails, the predicate constraint is not satisfied. We can make this work by moving the second reference to T::Type inside the requires-expression: template <class T> concept bool A = requires { typename T::Type; requires T::Type::value; }; template <class T> requires !A<T> void f() { } struct B { }; int main() { f<B>(); } Your testcase has this problem with Dereferenceable and Range, though fixing that doesn't make it work; I expect there's something else similar going on. This is a very subtle point. It seems to me that it would be better if creating the normal form of a constaint stops substituting into concept bodies once it's clear that we're inside an atomic constraint. So f would have a single atomic predicate constraint !A<T> and then when we consider this later we try to satisfy A<B>, which fails, so f's constraint is satisfied and the testcase succeeds. Though this does create an inconsistency in argument substitution behavior across the ! operator, which might be confusing. Any thoughts, Andrew?