c++ - 如何将 enable_if 用于互斥的非成员函数模板?

标签 c++ templates c++11 sfinae

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

#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>() )
{ /*...*/ }

我读过(这里是 S.O.)来解决成员函数模板的此类问题。 (有时,受访者将成员函数更改为成员函数模板以启用此功能。)但错误对我来说并没有改变。我是否必须切换到将 enable_if 放入返回类型?

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

最佳答案

有趣的是,一个 certain fellow here on SO不久前写了一篇博文,展示了一种很好的 C++11 风格的 SFINAE 技术,可以轻松地允许重载函数。提供了技术和解释here .

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

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 会发生什么?在那种情况下,两种过载都不可行。

关于c++ - 如何将 enable_if 用于互斥的非成员函数模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10861992/

相关文章:

c++ - 插入已排序的 vector<unique_ptr<pair<>>> 时避免堆分配

c++ - linux voip库

c++ - 将元素从一个数组复制到另一个 C++

python - 如何以自定义方式呈现 CheckboxGroup(或任何其他元素)?

c++ - 模板警告和错误帮助,(gcc)

c++ - 在模板参数中查找 typename 的 typename

c++ - typedefing 函数返回类型

c++ - 如何检查类型是否属于给定的模板类型

c++ - 如果程序的一部分表现出未定义的行为,它会影响程序的其余部分吗?

具有引用计数的 C++ 指针容器