6

我正在尝试编写非成员运算符函数模板,例如:

#include <utility>

template < typename T, unsigned L >
class MyType;

template < typename T, typename U, unsigned L >
auto  operator ==( MyType<T,L> const &l, MyType<U,L> const &r )
 -> decltype( std::declval<T>() == std::declval<U>() )
{ /*...*/ }

但是当我尝试处理何时lr有不同的长度时:

template < typename T, unsigned Lt, typename U, unsigned Lu, class Enable = typename std::enable_if<(Lt < Lu)>::type >
auto  operator ==( MyType<T,Lt> const &l, MyType<U,Lu> const &r )
 -> decltype( std::declval<T>() == std::declval<U>() )
{ /*...*/ }

template < typename T, unsigned Lt, typename U, unsigned Lu, class Enable = typename std::enable_if<(Lt > Lu)>::type >
auto  operator ==( MyType<T,Lt> const &l, MyType<U,Lu> const &r )
 -> decltype( std::declval<T>() == std::declval<U>() )
{ /*...*/ }

我得到模棱两可的错误。我试过类似的东西:

template < typename T, unsigned Lt, typename U, unsigned Lu, bool B = (Lt < Lu), class Enable = typename std::enable_if<B>::type >
auto  operator ==( MyType<T,Lt> const &l, MyType<U,Lu> const &r )
 -> decltype( std::declval<T>() == std::declval<U>() )
{ /*...*/ }

template < typename T, unsigned Lt, typename U, unsigned Lu, bool B = (Lt > Lu), class Enable = typename std::enable_if<B>::type >
auto  operator ==( MyType<T,Lt> const &l, MyType<U,Lu> const &r )
 -> decltype( std::declval<T>() == std::declval<U>() )
{ /*...*/ }

我已经阅读过(在 SO 上)来解决成员函数模板的此类问题。(有时,受访者将成员函数更改为成员函数模板以启用此功能。)但错误对我来说并没有改变。我必须切换到enable_if返回类型吗?

哦,当两个元素类型无法比较时,返回类型表达式应该排除这个运算符。它真的会起作用吗?它也与将enable_if周围放在那里兼容吗?

4

1 回答 1

11

有趣的是,SO 上的某个人不久前写了一篇博文,展示了一种很好的 C++11 风格的 SFINAE 技术,可以轻松实现重载函数。这里提供了技术和解释。

简而言之,您的代码失败了,因为两个模板在第一次解析和解析非依赖声明时,在类型方面完全相同。与默认函数参数一样,只有在实际调用函数时才会替换默认模板参数。这是两个模板在声明时对编译器的外观:

template<class T, unsigned Lt, class U, unsigned Lu, class Enable>
auto operator==(MyType<T,Lt> const& l, MyType<U,Lu> const& r);

以下代码应该可以实现您想要的:

namespace detail{
enum class enabler{};
}

template<bool B, class T = detail::enabler>
using EnableIf = typename std::enable_if<B, T>::type;

template < typename T, unsigned Lt, typename U, unsigned Lu, EnableIf<(Lt < Lu)>...>
auto  operator ==( MyType<T,Lt> const &l, MyType<U,Lu> const &r )
 -> decltype( std::declval<T>() == std::declval<U>() )
{ /*...*/ }

template < typename T, unsigned Lt, typename U, unsigned Lu, EnableIf<(Lt > Lu)>...>
auto  operator ==( MyType<T,Lt> const &l, MyType<U,Lu> const &r )
 -> decltype( std::declval<T>() == std::declval<U>() )
{ /*...*/ }

然而,一个问题仍然存在……如果 会发生Lt == Lu什么?在那种情况下,这两种过载都是不可行的。

于 2012-06-02T12:45:55.310 回答