首页 > 解决方案 > 带有 numeric_limits 的 SFINAE::max() 在 MSVC2017 上

问题描述

以下代码:

template <typename T, typename U>
typename std::enable_if<
    std::numeric_limits<T>::max() == std::numeric_limits<U>::max(),
    bool>::type
same_max() {
    return true;
}

template <typename T, typename U>
typename std::enable_if<
    std::numeric_limits<T>::max() != std::numeric_limits<U>::max(),
    bool>::type
same_max() {
    return false;
}

无法在 MSVC2017 上编译(在 gcc/clang 上正常),出现以下错误:

error C2995: 'std::enable_if<,bool>::type same_max(void)': function template has already been defined

这是我的 SFINAE 的问题,还是 MSVC 中的错误?

注意:使用std::numeric_limits<T>::is_signed(or std::is_signed<T>::value) 而不是std::numeric_limits<T>::max()编译得很好:

template <typename T, typename U>
typename std::enable_if<
    std::is_signed<T>::value == std::is_signed<U>::value,
    bool>::type
same_signedness() {
    return true;
}

template <typename T, typename U>
typename std::enable_if<
    std::is_signed<T>::value != std::is_signed<U>::value,
    bool>::type
same_signedness() {
    return false;
}

标签: c++visual-c++sfinaeenable-ifnumeric-limits

解决方案


这绝对看起来像是编译器中的错误。它不接受 SFINAE 中的成员函数(请注意,问题中的代码不仅对于min()/失败max(),而且对于任何类似epsilon()or的成员函数都失败lowest()),但它确实接受成员常量。您可以使用以下简单的解决方法和额外的间接级别struct(如果仅限于 C++11):

template<typename T>
struct get_max {
    static constexpr T value = std::numeric_limits<T>::max();
};

template <typename T, typename U>
typename std::enable_if<get_max<T>::value == get_max<U>::value, bool>::type
same_max() {
    return true;
}

template <typename T, typename U>
typename std::enable_if<get_max<T>::value != get_max<U>::value, bool>::type
same_max() {
    return false;
}

或变量模板(C++14 起):

template<typename T>
inline constexpr T get_max_v = std::numeric_limits<T>::max();

template <typename T, typename U>
std::enable_if_t<get_max_v<T> == get_max_v<U>, bool>
same_max() {
    return true;
}

template <typename T, typename U>
std::enable_if_t<get_max_v<T> != get_max_v<U>, bool>
same_max() {
    return false;
}

min为避免在某些头文件(如 )中定义的/max宏的潜在问题windef.h,函数名可以用括号括起来:

... = (std::numeric_limits<T>::max)();

推荐阅读