C++ Logo

std-proposals

Advanced search

Re: Making bit_cast Useful

From: Andrew Giese <gieseanw_at_[hidden]>
Date: Thu, 24 Sep 2020 07:49:43 -0500
>
> * If r is an expression of type T, the expression std::bit_cast<T>(r)
> shall be equivalent to copy constructing the result from r, except that the
> expression treats copy constructors which are defined as deleted as though
> they were defined as default instead, and does not call move constructors
> even if r is an rvalue.


std::bit_cast only works for types that are TriviallyCopyable, and will
emit a compiler error otherwise. This "Reflexive" case seems perhaps
unnecessary then.


On Thu, Sep 24, 2020 at 7:13 AM connor horman via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> C++20 added the function std::bit_cast to the standard library. While the
> result of it is defined, simply reinterpreting the bytes making up the
> object-representation, there are actually no defined results (beyond the
> identity case, which is simply copy-constructing the result from the
> input). This seeks to add limitations on the results of std::bit_cast,
> which are believed to be reasonable, and may be expected in practice.
>
> Reflexive:
> (Included for completeness)
> * If r is an expression of type T, the expression std::bit_cast<T>(r)
> shall be equivalent to copy constructing the result from r, except that the
> expression treats copy constructors which are defined as deleted as though
> they were defined as default instead, and does not call move constructors
> even if r is an rvalue.
>
> Enumerations and Integral types:
> * If r is an expression of a (potentially cv-qualified) integral type
> other than bool or an enumeration type, and U is a
> (potentially cv-qualified) integral type other than bool or an enumeration
> type, the expression std::bit_cast<U>(r), if well formed, shall be an
> equivalent expression to static_cast<U>(r)
>
>
> Pointer types:
> * If r is an expression of type (potentially cv-qualified) pointer to void
> or pointer to a character type, and U such a type, let P be the same
> pointer type as the type or r, but with the same cv-qualifiers (ignoring
> top-level cv-qualifiers) as U, the expression std::bit_cast<U>(r) shall be
> well-formed and shall be an equivalent expression as
> reinterpret_cast<U>(const_cast<P>(r))
> * If r is an expression of type T*, and U is the same type as T ignoring
> top level cv-qualifiers, then the expression std::bit_cast<U>(r) shall be
> well-formed, and shall be an equivalent expression to const_cast<U*>(r)
>
> Pointer-interconvertible:
> * If r is an (potentially const-qualified) lvalue, designating an object
> a, and U is a type, such that (ignoring all top-level cv-qualifiers), there
> is an object of type U, b, that is *pointer-interconvertible* with a,
> then the expression std::bit_cast<U>(r), if well formed, is equivalent to
> copy-constructing the result from a const-qualified lvalue designating b.
>
> Union:
> * If r is an expression of type T, and U is a union type which has at
> least one member of type T which is not a bitfield, if the expression
> std::bit_cast<U>(r), if well-formed, shall yield a union where the active
> member is the member of type T and is initialized as though by
> std::bit_cast<T>(r). If there are multiple such members, the active member
> is the first such member accessed by the program, or otherwise an
> unspecified member of that type. If the union has a member of a reference
> type, the behaviour is undefined.
>
> reference_wrapper:
> * If r is an expression of type std::reference_wrapper<T>and U is
> (possibly differently cv-qualified) T, then the expression
> std::bit_cast<U*>(r), shall be well-formed and an equivalent expression to
> const_cast<U*>(std::addressof(static_cast<T&>(r)))
> * If r is an expression of type T*, which points to an object, and U is
> (possibly differently cv-qualified) T, then the expression
> std::bit_cast<std::reference_wrapper<U>>(r) shall be well-formed, and an
> equivalent expression to std::ref(*const_cast<U*>(r)). If r does not point
> to an object, the behaviour is undefined. If T is an incomplete type other
> than (possibly cv-qualified) void or an array of unknown bound, the
> expression treats T as though it was completed. If T is an array of unknown
> bound, the expression treats T as though it were an array with length 1.
>
>
> Unresolved Questions:
> std::optional<std::reference_wrapper<T>> is currently not treated
> separately. It may be nice to apply a similar pair of rules as for regular
> std::reference_wrapper, with the additional clause that an empty optional
> bit_casts to a null pointer and the reverse. However, unlike the
> reference_wrapper requirements which are effective in libstdc++ and libc++
> (because its implemented with a single raw pointer member),
> std::optional<std::reference_wrapper<T>> is not implemented as such (though
> libc++ interestingly implements the storage for std::optional<T&> in case
> the standard ever decides to permit it, and this is done simply using a raw
> pointer). A possibility is not enforcing well-formedness, but keeping the
> behaviour if it is well-formed.
>
> These rules allow you to construct union values (provided the union is the
> same size as the member). Would it be reasonable to also allow the
> construction of Trivially Copyable, Standard Layout structure types with a
> single member of the source type?
>
> None of these rules cover transitive bit casts. Would it be reasonable to
> require such over all of these rules, or just a limited case (for example,
> void*->reference_wrapper<char>)?
>
> The reference_wrapper rules don't allow void*->reference_wrapper<void>. Is
> there a reason to allow this? Can reference_wrapper<void> exist?
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2020-09-24 07:49:58