https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102396
--- Comment #4 from Giuseppe D'Angelo <dangelog at gmail dot com> --- To elaborate on the last comment, this testcase does complain about the redefinition. #include <type_traits> #include <concepts> template <typename T> class S; template <typename T> static inline std::true_type is_S_impl(const S<T>&); static inline std::false_type is_S_impl(...); template <typename T> concept is_S = decltype(is_S_impl(std::declval<T>()))::value; template <typename T> struct S { using type = T; T data; S(); explicit S(const T &); template <typename V, typename U> requires is_S<V> && (!is_S<U>) && std::equality_comparable_with<typename V::type, U> friend bool operator==(const V &v, const U &u) { return v.data == u; } }; void f() { S<int> s1; s1 == 123; S<double> s2; s2 == 123.4; }