There are two binary logical operations on constraints: conjunction
and disjunction.

[*Example 1*: template<typename T>
constexpr bool get_value() { return T::value; }
template<typename T>
requires (sizeof(T) > 1) && (get_value<T>())
void f(T); // has associated constraint sizeof(T) > 1 get_value<T>()
void f(int);
f('a'); // OK, calls f(int)
*end example*]

In the satisfaction of the associated constraints
of f, the constraint sizeof(char) > 1 is not satisfied;
the second operand is not checked for satisfaction.

— [*Note 2*: — *end note*]

A logical negation expression ([expr.unary.op]) is an atomic constraint;
the negation operator is not treated as a logical operation on constraints.

As a result, distinct negation *constraint-expression**s*
that are equivalent under [temp.over.link]
do not subsume one another under [temp.constr.order].

Furthermore, if substitution to determine
whether an atomic constraint is satisfied ([temp.constr.atomic])
encounters a substitution failure, the constraint is not satisfied,
regardless of the presence of a negation operator.

[*Example 2*: template <class T> concept sad = false;
template <class T> int f1(T) requires (!sad<T>);
template <class T> int f1(T) requires (!sad<T>) && true;
int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions ([temp.constr.atomic])
// are not formed from the same *expression*
template <class T> concept not_sad = !sad<T>;
template <class T> int f2(T) requires not_sad<T>;
template <class T> int f2(T) requires not_sad<T> && true;
int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sad
template <class T> int f3(T) requires (!sad<typename T::type>);
int i3 = f3(42); // error: associated constraints not satisfied due to substitution failure
template <class T> concept sad_nested_type = sad<typename T::type>;
template <class T> int f4(T) requires (!sad_nested_type<T>);
int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
*end example*]

Here,
requires (!sad<typename T::type>) requires
that there is a nested type that is not sad,
whereas
requires (!sad_nested_type<T>) requires
that there is no sad nested type.

—