https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102396

--- Comment #5 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to Giuseppe D'Angelo from comment #3)
> Hello Patrick,
> 
> Thank you for the insights. I'm left wondering however if the CWG resolution
> would possibly ever allow the operator== to be defined as a hidden friend;
> the workaround you mentioned may lead to redefinition errors (as now it
> doesn't depend on S any more)?

Ah yeah, I ran into a similar issue when implementing the pipe operator for
range adaptor closures in libstdc++... IIRC, I worked around this by
introducing a non-template base class and defining the hidden template friend
in the base class instead.  So something like:

#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;

struct S_Base {
    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; }
};

template <typename T>
struct S : private S_Base {
    using type = T;
    T data;

    S();
    explicit S(const T &);
};

void f() {
    S<int> s1; s1 == 123;
    S<double> s2; s2 == 123.4;
}

Reply via email to