Skip to content

Add MR::bit_cast, usable without std::bit_cast - #6599

Merged
Fedr merged 4 commits into
masterfrom
fastint-builtin-bit-cast
Aug 18, 2026
Merged

Add MR::bit_cast, usable without std::bit_cast#6599
Fedr merged 4 commits into
masterfrom
fastint-builtin-bit-cast

Conversation

@Fedr

@Fedr Fedr commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

exp2i in MRFastInt.cpp uses std::bit_cast, which is not available in every libc++ MeshLib is built against. It breaks the MeshInspectorCode macOS x64 build, where brew clang 22 is pointed at the Xcode 14.2 SDK's libc++ (-nostdinc++ -isystem .../MacOSX.sdk/usr/include/c++/v1):

MeshLib/source/MRMesh/MRFastInt.cpp:23:17: error: no member named 'bit_cast' in namespace 'std'; did you mean 'bad_cast'?
   23 |     return std::bit_cast<double>( std::uint64_t( e + cMaxDoubleExp ) << 52 );
      |                 ^~~~~~~~
MeshLib/source/MRMesh/MRFastInt.cpp:23:32: error: expected '(' for function-style cast or type construction
2 errors generated.

<bit> is included; that libc++ simply predates the bit_cast wrapper. MRIsNaN.h and MRMeshLoad.cpp already knew about the gap, and each carried its own #if __cpp_lib_bit_cast >= 201806L with a different fallback.

New MRBitCast.h holds that choice once:

template <typename To, typename From>
[[nodiscard]] constexpr To bit_cast( const From& from ) noexcept
{
#if __cpp_lib_bit_cast >= 201806L
    return std::bit_cast<To>( from );
#else
    return __builtin_bit_cast( To, from );
#endif
}

std::bit_cast forwards to __builtin_bit_cast anyway, so the fallback is the same operation without the library wrapper, and it is available in clang 9+, GCC 11+ and MSVC 19.26+ (VS 2019 16.6) — all far below what -std=c++23 already requires. The header includes <version> before testing the feature macro, so the test is not at the mercy of what some other header happened to pull in.

All three call sites now use MR::bit_cast, and the #if is gone from everywhere else. Both fallbacks go with it: isNanFast no longer degrades to std::isnan, and binary STL vertex reading no longer degrades to std::memcpy — a bit-cast is what both wanted on every platform.

Checked on Godbolt, with both branches of the #if forced, that the whole set — the constexpr NaN bit pattern, the std::array<char, 12> -> Vector3f cast and exp2i — compiles clean under -Wall -Wextra -Werror -pedantic-errors on GCC 12/14/15, clang 16/20 and MSVC latest. The generated code is byte-identical between the two branches, so nothing about this is a pessimisation on the standard path.

Incidental: MRMeshLoad.cpp never included <cstring> for the std::memcpy in its fallback branch, so that branch depended on a transitive include to compile at all. MRIsNaN.h no longer needs <bit> or <cmath> directly. MRFastInt.cpp keeps <bit> for std::countl_zero, which that old libc++ does provide.

MeshLib's own CI cannot reproduce the original failure: build-test-macos.yml compiles on macos-15-intel and macos-14, both with a recent SDK. macos-12-intel appears there only as an install/test target. The failing compile is in the downstream MeshInspectorCode build.

Fedr added 2 commits August 17, 2026 23:19
std::bit_cast is missing from the Xcode 14.2 SDK's libc++, which the MeshInspectorCode macOS x64 build compiles against, and MRIsNaN.h already guards against the same gap. The builtin needs no library support and is available in every compiler that builds MeshLib.
isNanFast no longer degrades to std::isnan, and binary STL vertex reading no longer degrades to std::memcpy, on a standard library without std::bit_cast: the builtin needs none. MRMeshLoad.cpp never included <cstring> for that memcpy anyway.
@Fedr Fedr changed the title Use __builtin_bit_cast in exp2i Use __builtin_bit_cast instead of std::bit_cast Aug 17, 2026
It forwards to std::bit_cast where the standard library has it, and to the __builtin_bit_cast intrinsic otherwise, so the choice lives in one header instead of at every call site. The three call sites now use it.
@Fedr Fedr changed the title Use __builtin_bit_cast instead of std::bit_cast Add MR::bit_cast, usable without std::bit_cast Aug 18, 2026
Comment thread source/MRMesh/MRBitCast.h Outdated
Comment thread source/MRMesh/MRFastInt.cpp Outdated
Comment thread source/MRMesh/MRFastInt.cpp
Comment thread source/MRMesh/MRIsNaN.h Outdated
Comment thread source/MRMesh/MRIsNaN.h Outdated
Comment thread source/MRMesh/MRMeshLoad.cpp
Comment thread source/MRMesh/MRMeshLoad.cpp Outdated
One-line comment on bit_cast; unqualified calls where the argument type has no associated namespace; drop <bit> from MRMeshLoad.cpp, which no longer uses anything from it.
@Fedr
Fedr merged commit 7779736 into master Aug 18, 2026
50 checks passed
@Fedr
Fedr deleted the fastint-builtin-bit-cast branch August 18, 2026 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants