SFINAE功能的"全能"?

dor*_*mon 2 c++ templates sfinae c++11

我正在尝试创建一个类型化的比较函数,为不同类型进行一些自定义比较.

 #include <type_traits>

template <typename T>
bool typedCompare(const T& lhs, const T& rhs)
{
    return lhs == rhs; // default case, use ==
}

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
typedCompare(const T& lhs, const T& rhs)
{
    return (lhs - rhs) < 1e-10;
}

int main()
{
    typedCompare(1, 1);
    typedCompare(1.0, 1.0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这里,我有一个特殊的版本double比较少量的差异(请忽略我没有使用的事实std::abs()).我有一些其他自定义类型,我需要做一些特殊的比较,我不能==因为某些原因改变他们的运算符.

此外,我仍然希望拥有一个采用==操作员的"全能"风格功能.我的问题是,在尝试编译此代码片段时,编译器抱怨这typedCompare(1.0, 1.0)是不明确的,它可以选择提供的两个函数中的任何一个.

为什么?我怎么能解决这个问题?

谢谢.

Edg*_*jān 6

为什么?

简而言之,您使用的SFINAE不正确,因此当您呼叫typedCompare双打时,两个功能模板都有效.

我怎么能解决这个问题?

在这种特殊情况下,修复SFINAE以使其正常工作:

template <typename T>
typename std::enable_if<!std::is_floating_point<T>::value, bool>::type
typedCompare(const T& lhs, const T& rhs)
{
    return lhs == rhs; // default case, use ==
}

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
typedCompare(const T& lhs, const T& rhs)
{
    return (lhs - rhs) < 1e-10;
}
Run Code Online (Sandbox Code Playgroud)

请注意,此解决方案在许多类型的自定义方面不是那么好.另一种方法是使用标签分派:

struct floating_point_tag {};
// other tags

template <typename T>
bool typedCompare(const T& lhs, const T& rhs, floating_point_tag) {
    return (lhs - rhs) < 1e-10;
}

// implementations for other tags

template <typename T>
bool typedCompare(const T& lhs, const T& rhs) {
    if (std::is_floating_point<T>::value) {
        return typedCompare(lhs, rhs, floating_point_tag{});
    }

    // other checks here

    return lhs == rhs;
}
Run Code Online (Sandbox Code Playgroud)

最后,使用C++ 17,您可以使用if constexpr:

template <typename T>
bool typedCompare(const T& lhs, const T& rhs) {
    if constexpr (std::is_floating_point<T>::value) {
        return (lhs - rhs) < 1e-10;
    } else { // add other if-else here
        return lhs == rhs;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 但是,想象一下,如果我们有10种我专注的类型,那么第一个函数的条件会爆炸吗? (2认同)