Date: Fri, 15 Aug 2025 20:58:25 +0200
On 9 August 2025 06:20:08 CEST, Jan Schultke via Std-Proposals <std-proposals_at_[hidden]> wrote:
>> Supposing that double is IEEE-754 binary64 and ptr has type double*,
>> is it safe to reinterpret_cast<std::float64_t*>(ptr) and then use it to read or modify memory
>> that is an array of doubles?
>> I could not find that this is allowed, so I would like to float the idea for such a proposal.
>
>Unless otherwise stated, this violates strict aliasing and it's not
>allowed. Even if the compiler manual says that you can do it, it's
>undefined behavior and wouldn't work in constant expressions.
>
>We arguably have the right tools to deal with this situation already.
>For scalars that you want to pass between libraries, you can
>std::bit_cast<double> or std::bit_cast<std::float64_t> at the library
>bounds. For blocks of mutable data, you can use
>std::start_lifetime_as_array to reinterpret the elements without
>accessing storage.
>
>The only problem that we have no solution for, and this also comes up
>a lot at library bounds where std::string_view/std::u8string_view are
>used, is the ability to reinterpret immutable data with any other
>type.
start_lifetime_as(_array) have const overloads. Maybe you are thinking of self-memmove.
Anyway, I wouldn't describe start_lifetime_as as the "right tool". It can very easily introduce UB elsewhere, as it necessarily ends the lifetime of the objects that were already there. This can be inappropriate in glue code between libraries, other than cases where the library gives you full ownership of some float buffer. But then it might be in vector<float> or something similar, where again, changing the type of elements is rather dodgy.
> If we were able to do that, this would break optimizations
>though since any write to a char could change the value of a char8_t,
>and any write to a double could change a std::float64_t, and vice
>versa.
I would rather have the interoperability than these optimizations.
>> Supposing that double is IEEE-754 binary64 and ptr has type double*,
>> is it safe to reinterpret_cast<std::float64_t*>(ptr) and then use it to read or modify memory
>> that is an array of doubles?
>> I could not find that this is allowed, so I would like to float the idea for such a proposal.
>
>Unless otherwise stated, this violates strict aliasing and it's not
>allowed. Even if the compiler manual says that you can do it, it's
>undefined behavior and wouldn't work in constant expressions.
>
>We arguably have the right tools to deal with this situation already.
>For scalars that you want to pass between libraries, you can
>std::bit_cast<double> or std::bit_cast<std::float64_t> at the library
>bounds. For blocks of mutable data, you can use
>std::start_lifetime_as_array to reinterpret the elements without
>accessing storage.
>
>The only problem that we have no solution for, and this also comes up
>a lot at library bounds where std::string_view/std::u8string_view are
>used, is the ability to reinterpret immutable data with any other
>type.
start_lifetime_as(_array) have const overloads. Maybe you are thinking of self-memmove.
Anyway, I wouldn't describe start_lifetime_as as the "right tool". It can very easily introduce UB elsewhere, as it necessarily ends the lifetime of the objects that were already there. This can be inappropriate in glue code between libraries, other than cases where the library gives you full ownership of some float buffer. But then it might be in vector<float> or something similar, where again, changing the type of elements is rather dodgy.
> If we were able to do that, this would break optimizations
>though since any write to a char could change the value of a char8_t,
>and any write to a double could change a std::float64_t, and vice
>versa.
I would rather have the interoperability than these optimizations.
Received on 2025-08-15 18:58:33