以下代码:
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
(或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;
}
这绝对看起来像编译器中的一个错误。它不接受SFINAE中的成员函数(请注意,问题中的代码不仅对min()
/max()
失败,而且对任何成员函数(如epsilon()
或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;
}
为了避免在某些标头(如windef.h
(中定义的min
/max
宏的潜在问题,函数名称可以用括号括起来:
... = (std::numeric_limits<T>::max)();