Add std.conv.bitCast (#10651)

* Add std.conv.bitCast

This helper function is a more readable alternative to the traditional
pointer-cast-based syntax for reinterpreting casts.

The name bitCast is used for this operation in several other languages,
including C++ [1], Swift [2], C# [3], Zig [4], and LLVM IR [5].

[1] https://en.cppreference.com/w/cpp/numeric/bit_cast
[2] https://developer.apple.com/documentation/swift/unsafebitcast(_:to:)
[3] https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.unsafe.bitcast
[4] https://ziglang.org/documentation/0.10.0/#bitCast
[5] https://llvm.org/docs/LangRef.html#bitcast-to-instruction

* Add changelog entry for std.conv.bitCast
This commit is contained in:
Paul Backus 2025-02-28 16:54:10 -05:00 committed by GitHub
parent ab9b5cb48d
commit 6722d0a50b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 50 additions and 0 deletions

14
changelog/bit-cast.dd Normal file
View file

@ -0,0 +1,14 @@
Added `std.conv.bitCast`
This convenience function allows reinterpreting casts to be written in a more
readable way.
---
uint n = 0xDEADBEEF;
// Before
writeln("Bytes of n are: ", *cast(const ubyte[4]*) &n);
// After
writeln("Bytes of n are: ", n.bitCast!(const ubyte[4]));
---

View file

@ -13,6 +13,7 @@ $(TR $(TD Generic) $(TD
$(LREF parse)
$(LREF to)
$(LREF toChars)
$(LREF bitCast)
))
$(TR $(TD Strings) $(TD
$(LREF text)
@ -6047,3 +6048,38 @@ package enum toCtString(ulong n) = n.stringof[0 .. $ - "LU".length];
assert(toCtString!0 == "0");
assert(toCtString!123456 == "123456");
}
/**
* Takes the raw bits of a value and reinterprets them as a different type.
*
* Params:
* T = the new type.
* value = the value to reinterpret.
*
* Returns: a reference to the reinterpreted value.
*/
pragma(inline, true)
ref T bitCast(T, S)(ref S value)
if (T.sizeof <= S.sizeof)
{
return *cast(T*) &value;
}
///
@safe unittest
{
uint n = 0xDEADBEEF;
version (LittleEndian)
assert(n.bitCast!(ubyte[4]) == [0xEF, 0xBE, 0xAD, 0xDE]);
version (BigEndian)
assert(n.bitCast!(ubyte[4]) == [0xDE, 0xAD, 0xBE, 0xEF]);
}
// Sizes must be compatible
@safe unittest
{
uint n;
assert(!__traits(compiles, n.bitCast!ulong));
}