这与我之前的文章';fpcategory';:对重载函数的模糊调用
我试图更正产生错误的代码。原始代码如下所示。
struct alignas(1) wrapped_int8 {
using underlying = int8_t;
int8_t value;
// some other function definitions
};
template <typename T>
void func(T val) {
auto mask = std::isnan(val);
}
int main(int argc, char const *argv[])
{
func<wrapped_int8::underlying>(4);
}
由于fpclassify
重载模糊性问题以及microsoft内部版本缺少对fpclassify
的积分重载,它无法使用microsoft编译器进行编译。
所以我把func
改成:
template <typename T>
void func(T val) {
auto mask = std::is_integral<T>::value ? false : std::isnan(val);
}
但这仍然给出了相同的错误。根据我的代码逻辑,如果T
是积分类型,我们就不应该调用std::isnan
,所以fpclassify
应该不会有问题,但编译器是否足够聪明,知道不会在积分类型上调用std::isnan
?如果是这样,为什么它仍然会产生这个错误?如果没有,我该如何解决此问题?
您可以使用if constexpr
放弃对std::isnan(val)
的调用。
template <typename T>
void func(T val) {
auto mask = [&] {
if constexpr (std::is_integral_v<T>)
return false;
else
return std::isnan(val);
}();
}
C++14版本
template<class T>
constexpr typename std::enable_if<std::is_integral_v<T>, bool>::type
mask_impl(T val) {
return false;
}
template<class T>
constexpr typename std::enable_if<std::is_floating_point_v<T>, bool>::type
mask_impl(T val) {
return std::isnan(val);
}
template <typename T>
void func(T val) {
auto mask = mask_impl(val);
}
如果允许C++17
template <typename T>
void func(T val) {
auto mask = false;
if constexpr (!std::is_integral<T>::value)
mask = std::isnan(val);
}
如果是C++14或更早的
template <typename T>
void func(T val) {
auto mask = std::isnan(val);
}
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void func(T val) {
auto mask = false;
}
你也可以破解std::isnan
的int8_t
namespace std {
bool isnan(int8_t val) noexcept { return false; }
}