diff --git a/include/fastgltf/tools.hpp b/include/fastgltf/tools.hpp index c820db188..3f1013fd8 100644 --- a/include/fastgltf/tools.hpp +++ b/include/fastgltf/tools.hpp @@ -142,7 +142,10 @@ constexpr T deserializeComponent(const std::byte* bytes, std::size_t index) { } template<> -constexpr float deserializeComponent(const std::byte* bytes, std::size_t index) { +#if FASTGLTF_CONSTEXPR_BITCAST +constexpr +#endif +float deserializeComponent(const std::byte* bytes, std::size_t index) { static_assert(std::numeric_limits::is_iec559 && std::numeric_limits::radix == 2 && std::numeric_limits::digits == 24 && @@ -152,7 +155,10 @@ constexpr float deserializeComponent(const std::byte* bytes, std::size_t } template<> -constexpr double deserializeComponent(const std::byte* bytes, std::size_t index) { +#if FASTGLTF_CONSTEXPR_BITCAST +constexpr +#endif +double deserializeComponent(const std::byte* bytes, std::size_t index) { static_assert(std::numeric_limits::is_iec559 && std::numeric_limits::radix == 2 && std::numeric_limits::digits == 53 && diff --git a/include/fastgltf/util.hpp b/include/fastgltf/util.hpp index 4ff22dd3f..a69039842 100644 --- a/include/fastgltf/util.hpp +++ b/include/fastgltf/util.hpp @@ -75,6 +75,12 @@ #define FASTGLTF_UNREACHABLE assert(0); #endif +#if defined(__has_builtin) +#define FASTGLTF_HAS_BUILTIN(x) __has_builtin(x) +#else +#define FASTGLTF_HAS_BUILTIN(x) 0 +#endif + #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 5030) // attribute 'x' is not recognized @@ -328,14 +334,29 @@ namespace fastgltf { return static_cast(op to_underlying(a)); \ } - // Simple non-constexpr bit_cast implementation. +#if FASTGLTF_CPP_20 && defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +#define FASTGLTF_CONSTEXPR_BITCAST 1 + template + [[nodiscard]] constexpr To bit_cast(const From& from) noexcept { + return std::bit_cast(from); + } +#elif (defined(__clang__) || __clang_major__ >= 9) || (defined(__GNUC__) && __GNUC__ >= 11) || FASTGLTF_HAS_BUILTIN(__builtin_bit_cast) +#define FASTGLTF_CONSTEXPR_BITCAST 1 + template + [[nodiscard]] constexpr To bit_cast(const From& from) noexcept { + // Available since Clang 9, GCC 11.1, and MSVC 16.6. Otherwise, this function could not be constexpr. + return __builtin_bit_cast(To, from); + } +#else +#define FASTGLTF_CONSTEXPR_BITCAST 0 template - To bit_cast(const From& from) noexcept { + [[nodiscard]] To bit_cast(const From& from) noexcept { static_assert(std::is_trivially_constructible_v); To dst; std::memcpy(&dst, &from, sizeof(To)); return dst; } +#endif } // namespace fastgltf #ifdef _MSC_VER