在具有隐式转换的模板类外部重载运算符

Operator overloading outside a template class with implicit conversions

本文关键字:外部 重载 运算符 转换      更新时间:2023-10-16

我有一个像一样定义的模板类

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>,而另一个不是时,如何使其支持隐式转换。我不想为每个可能的排列编写每个运算符的多个声明。

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
}

其他人会更好地表达这一点,但我认为问题是,如果不向编译器传递Wrap对象,编译器就无法在Wrap<T>中推导出T。我认为,如果您明确地给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==进行许多意外的比较,甚至是int s、string s等。