This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/67070] [concepts] Concept with negation and disjunction not checked correctly
- From: "jason at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 31 Jul 2015 18:00:42 +0000
- Subject: [Bug c++/67070] [concepts] Concept with negation and disjunction not checked correctly
- Auto-submitted: auto-generated
- References: <bug-67070-4 at http dot gcc dot gnu dot org/bugzilla/>
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?