This paper is a revision of [P0476r0], addressing LEWG comments from the 2016 Issaquah meeting. See § 4 Revision History for details.
1. Background
Low-level code often seeks to interpret objects of one type as another: keep the
same bits, but obtain an object of a different type. Doing so correctly is
error-prone: using
or
runs afoul of type-aliasing
rules yet these are the intuitive solutions developers mistakenly turn to.
Attuned developers use
with
, avoiding alignment
pitfalls and allowing them to bit-cast non-default-constructible types.
This proposal uses appropriate concepts to prevent misuse. As the sample
implementation demonstrates we could as well use
or template
SFINAE, but the timing of this library feature will likely coincide with
concept’s standardization.
Furthermore, it is currently impossible to implement a
bit-cast
function, as
itself isn’t
. Marking the proposed function as
doesn’t require or prevent
from becoming
. This
leaves implementations free to use their own internal solution (e.g. LLVM has a
opcode).
We should standardize this oft-used idiom, and avoid the pitfalls once and for all.
2. Proposed Wording
Below, substitute the �
character with a number the editor finds appropriate
for the sub-section.
2.1. Synopsis
Under 20.2 Header
synopsis [utility]:
namespace std { // ... // 20.2.� bit-casting: template < typename To , typename From > requires sizeof ( To ) == sizeof ( From ) && is_trivially_copyable_v < To > && is_trivially_copyable_v < From > constexpr To bit_cast ( const From & from ) noexcept ; // ... }
2.2. Details
Under 20.2.�
Bit-casting [utility.bitcast]:
template < typename To , typename From > requires sizeof ( To ) == sizeof ( From ) && is_trivially_copyable_v < To > && is_trivially_copyable_v < From > constexpr To bit_cast ( const From & from ) noexcept ;
-
Requires:
,sizeof ( To ) == sizeof ( From )
isis_trivially_copyable_v < To > true
,
isis_trivially_copyable_v < From > true
. -
Returns: an object of type
whose object representation is equal to the object representation ofTo
. If multiple object representations could represent the value representation ofFrom
, then it is unspecified whichFrom
value is returned. If no value representation corresponds toTo
's object representation then the returned value is unspecified.To
2.3. Feature testing
The
feature test macro should be added.
3. Appendix
The Standard’s [basic.types] section explicitly blesses
:
For any trivially copyable type
, if two pointers to
T point to distinct
T objects
T and
obj1 , where neither
obj2 nor
obj1 is a base-class subobject, if the underlying bytes (1.7) making up
obj2 are copied into
obj1 ,
obj2 shall subsequently hold the same value as
obj2 .
obj1 [Example:
— end example]T * t1p ; T * t2p ; // provided that t2p points to an initialized object ... std :: memcpy ( t1p , t2p , sizeof ( T )); // at this point, every subobject of trivially copyable type in *t1p contains // the same value as the corresponding subobject in *t2p
Whereas section [class.union] says:
In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
4. Revision History
4.1. r0 ➡ r1
The paper was reviewed by LEWG at the 2016 Issaquah meeting:
-
Remove the standard layout requirement—trivially copyable suffices for the
requirement.memcpy -
We discussed removing
, but there was no consent either way. There was some suggestion that it’ll be hard for implementers, but there’s also some desire (by the same implementers) to have those features available in order to support things likeconstexpr
instances ofconstexpr
.std :: variant -
The pointer-forbidding logic was removed. It was initially there to help developers when a better tool is available, but it’s easily worked around (e.g. with a
containing a pointer). Note that this doesn’t preventstruct
versions ofconstexpr
: the implementation is allowed to error out onbit_cast
of pointer.bit_cast -
Some discussion about concepts-usage, but it seems like mostly an LWG issue and we’re reasonably sure that concepts will land before this or in a compatible vehicle.
Straw polls:
-
Do we want to see [P0476r0] again? unanimous consent.
-
should allow pointer types inbit_cast
andTo
. SF F N A SA 4 5 4 2 1From -
should bebit_cast
? SF F N A SA 4 3 7 2 3constexpr
5. Acknowledgement
Thanks to Saam Barati, Jeffrey Yasskin, and Sam Benzaquen for their early review and suggested improvements.