Date: Wed, 27 Aug 2025 21:50:52 +0000
Thanks, Tom. I'd like to make the following observations:
> The goal is to temporarily replace objects of type A with objects of type B
> while preserving the object representation, then accessing/modifying
> the replacement objects using only type B, then replace the
> objects of type B with objects of type A while again
> preserving the object representation in such a way that
> pointers/references to the original set of objects transparently
> refer to the new set of objects. Key to making this work is
> specifying that these operations do not end the lifetime of any
> enclosing objects.
It seems that it would be a big change to the abstract machine if starting the lifetime of objects of type B did not end the lifetime of objects of type A (which formerly occupied the same storage).
> std::inplace_converting_array_cast<std::float64_t>(x.data(), x.size());
> std::inplace_converting_array_cast<std::float64_t>(y.data(), y.size());
>
> daxpy(n, std::bitcast<std::float64_t>(alpha), x.data(), y.data());
>
> std::inplace_converting_array_cast<double>(y.data(), y.size());
> std::inplace_converting_array_cast<double>(x.data(), x.size());
A minor point is that std::bitcast<std::float64_t>(alpha) is not needed. One can just write alpha and implicit conversion will work.
However, x.data() is still double*, so in the daxpy call one would need reinterpret_cast<std::float64_t*>(x.data()), and similarly for y.data().
So, std::inplace_converting_array_cast<std::float64_t> could, for convenience, return a std::float64_t*.
std::float64_t* x_ptr = std::inplace_converting_array_cast<std::float64_t>(x.data(), x.size());
std::float64_t* y_ptr = std::inplace_converting_array_cast<std::float64_t>(y.data(), y.size());
daxpy(n, alpha, x_ptr, y_ptr);
std::inplace_converting_array_cast<double>(y_ptr, y.size());
std::inplace_converting_array_cast<double>(x_ptr, x.size());
Though, it seems like a fundamental change that std::inplace_converting_array_cast() has the effect of laundering all pointers that point to a given address.
I think that's what it does--after all the code above, the vectors' pointers to double are again valid.
If that direction seems promising, it might be worth brainstorming on something more general.
Maybe, std::launder_all_pointers(void *, std::size_t)
Personally, I don't see this as promising and don't intend to propose it, but it is interesting, and I appreciate your time and effort.
It's worth noting that GCC, for example, has the flag -fno-strict-aliasing
Possibly compilers could offer something more restrictive, such as -fno-fp-strict-aliasing
That may be a practical solution, but then the code isn't really C++ any more; it's a custom dialect.
Received on 2025-08-27 21:50:55