在模板类之外使用运算符重载和隐式转换

7

我有一个模板类定义如下:

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个回答

4
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
}

很棒的答案。我猜你漏掉了“tc2”的引用。 - user1353535

1

有人会表达得更好,但我认为问题在于编译器无法推断出Wrap<T>中的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==进行许多意外比较,甚至包括intstring等。

这仍然需要我为每个我想避免的运算符添加2个其他声明。 - user1353535

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接