diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 3d4f14fc9cd552..35a465a99f2bd8 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -12,7 +12,6 @@ #include <__config> #include <__type_traits/enable_if.h> #include <__type_traits/is_arithmetic.h> -#include <__type_traits/is_floating_point.h> #include <__type_traits/is_integral.h> #include <__type_traits/is_signed.h> #include <__type_traits/promote.h> @@ -34,8 +33,21 @@ namespace __math { # define _LIBCPP_SIGNBIT_CONSTEXPR #endif -template ::value, int> = 0> -_LIBCPP_NODISCARD inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +// The universal C runtime (UCRT) in the WinSDK provides floating point overloads +// for std::signbit(). By defining our overloads as templates, we can work around +// this issue as templates are less preferred than non-template functions. +template +_LIBCPP_NODISCARD inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT { + return __builtin_signbit(__x); +} + +template +_LIBCPP_NODISCARD inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT { + return __builtin_signbit(__x); +} + +template +_LIBCPP_NODISCARD inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT { return __builtin_signbit(__x); } diff --git a/libcxx/test/std/numerics/c.math/signbit.pass.cpp b/libcxx/test/std/numerics/c.math/signbit.pass.cpp index c85033e363ce55..a8a566f7de6434 100644 --- a/libcxx/test/std/numerics/c.math/signbit.pass.cpp +++ b/libcxx/test/std/numerics/c.math/signbit.pass.cpp @@ -70,9 +70,22 @@ struct TestInt { } }; +template +struct ConvertibleTo { + operator T() const { return T(); } +}; + int main(int, char**) { types::for_each(types::floating_point_types(), TestFloat()); types::for_each(types::integral_types(), TestInt()); + // Make sure we can call `std::signbit` with convertible types. This checks + // whether overloads for all cv-unqualified floating-point types are working + // as expected. + { + assert(!std::signbit(ConvertibleTo())); + assert(!std::signbit(ConvertibleTo())); + assert(!std::signbit(ConvertibleTo())); + } return 0; }