In the following code why does the second and third concepts produce a compilation error?
#include <tuple>
template <class P>
concept IsPair1 = std::tuple_size<P>::value == 2;
template <class P>
concept IsPair2 = std::tuple_size_v<P> == 2;
template <class P>
concept IsPair3 = requires { typename std::tuple_size<P>; } && std::tuple_size_v<P> == 2;
constexpr bool intIsPair1 = IsPair1<int>; // OK, false
constexpr bool intIsPair2 = IsPair2<int>; // error: incomplete type 'std::tuple_size<int>' used in nested name specifier
constexpr bool intIsPair3 = IsPair3<int>; // error: incomplete type 'std::tuple_size<int>' used in nested name specifier
/usr/local/Cellar/gcc/11.1.0_1/include/c++/11.1.0/tuple:1334:61: error: incomplete type 'std::tuple_size<int>' used in nested name specifier
1334 | inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
| ^~~~~
I expected all three to be evaluated to false as according to https://en.cppreference.com/w/cpp/language/constraints,
Satisfaction of an atomic constraint is checked by substituting the parameter mapping and template arguments into the expression E. If the substitution results in an invalid type or expression, the constraint is not satisfied.