Date: Tue, 19 Aug 2025 22:47:53 +0200
On 18 August 2025 20:49:41 CEST, Paul Caprioli <paul_at_[hidden]> wrote:
>
>> We have magic aliasing properties for std::complex exactly to bridge some interoperability issues.
>> I don't really advocate for more magic, I would rather have a generic framework for having distinct types that can alias each other.
>> Then we can more freely decide for newly introduced types whether aliasing makes sense or not.
>
>Who is "we"? Are you suggesting a generic framework that allows programmers to pick and choose which distinct types can alias each other?
>It seems adding such capability to the standard library would lead to a great deal of undefined behavior, as it would be easy to violate the one definition rule.
>Also, there would be a temptation to unconditionally alias `double` and `std::float64_t` without checking whether the former is IEEE binary64.
>Practically speaking, it's a safe assumption, but then why have `std::float64_t` at all?
>The C++ standard can alias the two types if and only if they both have the same representation.
No, I agree, users of the language shouldn't be able to alter aliasing properties of builtin and standard library types, that would be insane. There might be room to customize that for user-defined types, but that might be difficult.
>Or may I assume that "we" is the C++ committee?
Either the committee or the implementers.
>But then the generic framework is just words in the standard that compilers have to honor, i.e., magic.
It could be no more magic than certain types having size 4 or alignment 8. Simply being a property of a pair of types, that could be queried with a standard trait and reflection. Some of this could be defined by the standard, like for complex, and mostly left as implementation-defined otherwise.
I don't know whether aliasing float64_t would be best defined by the standard or the implementation. Regardless, we could have a standard trait to query that.
>I agree it's important to make the words clear, and it seems "designates" is the magic word.
>As in, `reinterpret_cast<cv T*>(a)[2 * i]` designates the real part of `a[i]`.
>I also agree that newly introduced types should carefully consider whether aliasing makes sense or not.
>
>Referring to my earlier email, developers using daxypy want to write: daxpy(n, alpha, (std::float64_t*)(x.data()), (std::float64_t*)(y.data()));
>I predict that is how programs using `double` will access third-party libraries taking pointers to `std::float64_t`.
>
>We can:
>(1) Update the C++ standard to make that work.
>(2) Ignore that it is currently UB and rely on compilers to make it work anyway.
>(3) Educate programmers not to mix `double` and `std::float64_t`.
>(4) Educate programmers to memcpy x.data(), memcpy y.data(), call daxpy(), start_lifetime_as_array<double> on the returned array, and then y.assign().
>
>I suggest that (3) and (4) are equivalent to saying, "never use `std::float64_t`."
>Modern scientific codes rely on "icebergs of dependency libraries."
>See slides 7-8 of https://spack-tutorial.readthedocs.io/en/latest/_downloads/91891ebe189765703c6acb6a59528a15/spack-hpcic25-tutorial-slides.pdf
I agree. Adding a new distinct type that has the same object representation as some existing type adds this kind of friction with TBAA. I think this is also a major hurdle in adopting char8_t when a ton of existing libraries already store utf8 strings in char arrays.
Cheers,
Lénárd
>
>Best regards,
>Paul
>
>
>> We have magic aliasing properties for std::complex exactly to bridge some interoperability issues.
>> I don't really advocate for more magic, I would rather have a generic framework for having distinct types that can alias each other.
>> Then we can more freely decide for newly introduced types whether aliasing makes sense or not.
>
>Who is "we"? Are you suggesting a generic framework that allows programmers to pick and choose which distinct types can alias each other?
>It seems adding such capability to the standard library would lead to a great deal of undefined behavior, as it would be easy to violate the one definition rule.
>Also, there would be a temptation to unconditionally alias `double` and `std::float64_t` without checking whether the former is IEEE binary64.
>Practically speaking, it's a safe assumption, but then why have `std::float64_t` at all?
>The C++ standard can alias the two types if and only if they both have the same representation.
No, I agree, users of the language shouldn't be able to alter aliasing properties of builtin and standard library types, that would be insane. There might be room to customize that for user-defined types, but that might be difficult.
>Or may I assume that "we" is the C++ committee?
Either the committee or the implementers.
>But then the generic framework is just words in the standard that compilers have to honor, i.e., magic.
It could be no more magic than certain types having size 4 or alignment 8. Simply being a property of a pair of types, that could be queried with a standard trait and reflection. Some of this could be defined by the standard, like for complex, and mostly left as implementation-defined otherwise.
I don't know whether aliasing float64_t would be best defined by the standard or the implementation. Regardless, we could have a standard trait to query that.
>I agree it's important to make the words clear, and it seems "designates" is the magic word.
>As in, `reinterpret_cast<cv T*>(a)[2 * i]` designates the real part of `a[i]`.
>I also agree that newly introduced types should carefully consider whether aliasing makes sense or not.
>
>Referring to my earlier email, developers using daxypy want to write: daxpy(n, alpha, (std::float64_t*)(x.data()), (std::float64_t*)(y.data()));
>I predict that is how programs using `double` will access third-party libraries taking pointers to `std::float64_t`.
>
>We can:
>(1) Update the C++ standard to make that work.
>(2) Ignore that it is currently UB and rely on compilers to make it work anyway.
>(3) Educate programmers not to mix `double` and `std::float64_t`.
>(4) Educate programmers to memcpy x.data(), memcpy y.data(), call daxpy(), start_lifetime_as_array<double> on the returned array, and then y.assign().
>
>I suggest that (3) and (4) are equivalent to saying, "never use `std::float64_t`."
>Modern scientific codes rely on "icebergs of dependency libraries."
>See slides 7-8 of https://spack-tutorial.readthedocs.io/en/latest/_downloads/91891ebe189765703c6acb6a59528a15/spack-hpcic25-tutorial-slides.pdf
I agree. Adding a new distinct type that has the same object representation as some existing type adds this kind of friction with TBAA. I think this is also a major hurdle in adopting char8_t when a ton of existing libraries already store utf8 strings in char arrays.
Cheers,
Lénárd
>
>Best regards,
>Paul
>
Received on 2025-08-19 20:48:06