This is related to my earlier post 'fpclassify': ambiguous call to overloaded function
I attempted to correct the code that produced the error. The original code looked like the following.
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);
}
It failed to compile using microsoft compilers because of the fpclassify
overload ambiguity issue and the lack of an integral overload to fpclassify
for the microsoft build.
So I changed the func
to:
template <typename T>
void func(T val) {
auto mask = std::is_integral<T>::value ? false : std::isnan(val);
}
but this still gives the same error. With my code's logic, if T
is an integral type, we should never have to call std::isnan
, so there shouldn't be an issue with fpclassify
, but is the compiler smart enough to know that std::isnan
won't be called on integral types? If so, why is it still producing this error? If not, how can I fix this problem?
CodePudding user response:
you can use if constexpr
to discard the call to 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 version
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);
}
CodePudding user response:
If C 17 is allowed
template <typename T>
void func(T val) {
auto mask = false;
if constexpr (!std::is_integral<T>::value)
mask = std::isnan(val);
}
If C 14 or older
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;
}
You also may hack std::isnan
for int8_t
namespace std {
bool isnan(int8_t val) noexcept { return false; }
}