Skip to content

Commit

Permalink
Fix: Add constexpr bit_cast when available
Browse files Browse the repository at this point in the history
  • Loading branch information
spnda committed Feb 1, 2024
1 parent a27b881 commit 510e0c1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
10 changes: 8 additions & 2 deletions include/fastgltf/tools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ constexpr T deserializeComponent(const std::byte* bytes, std::size_t index) {
}

template<>
constexpr float deserializeComponent<float>(const std::byte* bytes, std::size_t index) {
#if FASTGLTF_CONSTEXPR_BITCAST
constexpr
#endif
float deserializeComponent<float>(const std::byte* bytes, std::size_t index) {
static_assert(std::numeric_limits<float>::is_iec559 &&
std::numeric_limits<float>::radix == 2 &&
std::numeric_limits<float>::digits == 24 &&
Expand All @@ -152,7 +155,10 @@ constexpr float deserializeComponent<float>(const std::byte* bytes, std::size_t
}

template<>
constexpr double deserializeComponent<double>(const std::byte* bytes, std::size_t index) {
#if FASTGLTF_CONSTEXPR_BITCAST
constexpr
#endif
double deserializeComponent<double>(const std::byte* bytes, std::size_t index) {
static_assert(std::numeric_limits<double>::is_iec559 &&
std::numeric_limits<double>::radix == 2 &&
std::numeric_limits<double>::digits == 53 &&
Expand Down
25 changes: 23 additions & 2 deletions include/fastgltf/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -328,14 +334,29 @@ namespace fastgltf {
return static_cast<T>(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<typename To, typename From>
[[nodiscard]] constexpr To bit_cast(const From& from) noexcept {
return std::bit_cast<To>(from);
}
#elif (defined(__clang__) || __clang_major__ >= 9) || (defined(__GNUC__) && __GNUC__ >= 11) || FASTGLTF_HAS_BUILTIN(__builtin_bit_cast)
#define FASTGLTF_CONSTEXPR_BITCAST 1
template<typename To, typename From>
[[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<typename To, typename From>
To bit_cast(const From& from) noexcept {
[[nodiscard]] To bit_cast(const From& from) noexcept {
static_assert(std::is_trivially_constructible_v<To>);
To dst;
std::memcpy(&dst, &from, sizeof(To));
return dst;
}
#endif
} // namespace fastgltf

#ifdef _MSC_VER
Expand Down

0 comments on commit 510e0c1

Please sign in to comment.