Different behavior of MSVC and clang for if constexpr branches

For bool at least two type traits return true:

std::is_same<bool, Type>::value
std::is_arithmetic<Type>::value

and then you make a call std::isnan(true). Use else if:

if constexpr (std::is_same<bool, Type>::value) {
    auto s = value ? "true" : "false";
    return encloseInQuotes ? "\""s + s + "\"" : s;
}
else if constexpr (std::is_arithmetic<Type>::value) {
    if (std::isnan(value)) {
        return encloseInQuotes ? "\"NaN\"" : "NaN";
    }
    ...
}
else
    return "";

std::isnan and std::isinf seemingly internally calls fpclassify in MSVC. This function is overloaded for floating-point types, and you pass an argument of type bool, thus the call is ambiguous.

To avoid this, you may cast the arguments, e.g., to double:

if constexpr (std::is_arithmetic<Type>::value) {
  if (std::isinf((double)value)) {
    return encloseInQuotes ? "\"INF\"" : "INF";
  }

  if (std::isnan((double)value)) {
    return encloseInQuotes ? "\"NaN\"" : "NaN";
  }

Live demo: https://godbolt.org/z/W7Z3r3


UPDATE

This seems to be a bug in MSVC implementation, since, according to cppreference, there should be an overload for integral arguments that behaves the same as the double overload. Minimal example:

auto b = std::isnan(1);

Live demo: https://godbolt.org/z/qcTfQs

Tags:

C++