Перегрузка оператора вне класса шаблона неявными преобразованиями

у меня есть класс шаблона, определенный следующим образом

template<class T> class Wrap
{
    /* ... */
public:
    Wrap(const T&);
    /* other implicit conversions */

    /* ... */
};

Я хочу, чтобы определить все операторы сравнения для этого класса вне класса, как это

template<typename T> bool operator == (const Wrap<T>&, const Wrap<T>&)
{
    // Do comparison here
}

однако это объявление не поддерживает неявные преобразования const T&, или любой другой тип, к const Wrap<T>&.

поэтому мой вопрос в том, как я могу сделать его поддержкой неявных преобразований, когда любой из операндов имеет тип Wrap<T> а другой нет. Я не хочу писать несколько объявления каждого оператора для каждой возможной перестановки.

2 ответов


template<class T> struct is_wrap : std::false_type {};
template<class T> struct is_wrap<Wrap<T>> : std::true_type {};

template<class T1, class T2> typename std::enable_if<is_wrap<typename std::common_type<T1, T2>::type>::value, bool>::type operator == (const T1& t1, const T2& t2)
{
    const typename std::common_type<T1, T2>::type& tc1 = t1, tc2 = t2;
    // compare with tc1 and tc2
}

кто-то другой сформулирует это лучше, но я думаю, что проблема в том, что компилятор не может вывести T на Wrap<T> без вас проходя его Wrap "объект". Я думаю, что ваша ситуация должна быть решена, если вы явно даете operator== аргумент шаблона: operator==<int>(7, 4), например, должен работать.

у меня нет компилятора передо мной, но вот моя попытка:

template<typename T>
typename std::enable_if<std::is_convertible<Wrap<T>, T>::value, bool>::type operator==(const Wrap<T>& l, const T& r)
{
    return l.stuff == Wrap<T>(r).stuff;
}

template<typename T>
typename std::enable_if<std::is_convertible<Wrap<T>, T>::value, bool>::type operator==(const T& l, const Wrap<T>& r)
{
    return r == l; // call above operator
}

это должно работать, если любая из сторон является Wrap а другая сторона-нет. Ты мог бы ... также сделайте обе стороны как const T&, однако, если Wrap действительно неявно конструируется из любого T вы закончите с помощью вашего operator== для многих непреднамеренных сравнений, даже ints,strings, etc.