template <class T, class U>
concept SubClass = std::is_base_of<U, T>::value;
used in this context:
void f(X); // X is constrained by SubClass<X, ABase>
seems inverted to me: the first template argument to SubClass should correspond to the template parameter T in which case X is constrained by SubClass<ABase,X>.
in other words by std::is_base_of<X, ABase>::value
yet the 1ste argument to is_base_of is supposed to be the base class, the second the derived class