C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Complex type traits

From: Tom Honermann <tom_at_[hidden]>
Date: Mon, 27 Nov 2023 16:33:24 -0500
On 11/24/23 1:13 PM, Paul Caprioli via Std-Proposals wrote:
> Thanks, Tom.
>
> I'd like to offer an observation regarding P2098. Since the template specializations of std::complex<T> were removed in C++23, std::complex<float> instantiates the primary template. So it may not be immediately obvious that the following is true: std::is_specialization_of_v<std::complex<float>, std::complex>
>
> Also, considering the following,
>
> struct MyFloat { uint64_t data[8]; };
> using T = std::numeric_limits<MyFloat>;
> static_assert(not T::is_specialized);
> static_assert(std::is_specialization_of_v<T, std::numeric_limits>);
>
> perhaps teachability and the readability of user code could be improved by some other name. One thought that comes to mind is
>
> std::is_instance_of_v<T, std::numeric_limits>
>
In my opinion, std::is_specialization_of_v is the right name. I am aware
that there are programmers that are not familiar with some of the
terminology and are unaware that a (explicit or implicit) template
instantiation and an explicit specialization both produce a
specialization of the primary template. But I don't find that a
motivating reason to add additional terminology. The terminology that we
have now is consistent and teachable (but perhaps not taught enough).

In general, I don't think we should expose whether a template
specialization was produced from an instantiation of a (partial)
template or an explicit specialization. The distinction should not
matter for users of these types. If std::numeric_limits were being
designed today, I don't think it would have a is_specialized data
member. I think we would instead specify an incomplete primary class
template and expect SFINAE or concepts to be used to determine when an
explicit specialization is needed.

Tom.

> Regards,
> Paul
>
>
> -----Original message-----
> From: Tom Honermann <tom_at_[hidden]>
> Sent: Monday, November 20 2023, 9:21 am
> To: std-proposals_at_[hidden] <std-proposals_at_[hidden]>
> Cc: Paul Caprioli <paul_at_[hidden]>
> Subject: Re: [std-proposals] Complex type traits
>
> Previous proposals have explored such traits. See:
>
> P2078 <https://wg21.link/p2078>: Add new traits
> type std::is_complex<T>
> P2098 <https://wg21.link/p2098>: Proposing std::is_specialization_of
>
> Progress on P2078 is blocked on further work by its author.
>
> Progress on P2098 is blocked on a proposal that doesn't have the
> limitations described in the paper. I believe the adoption of P2989 (A Simple Approach to
> Universal Template Parameters) <https://wg21.link/p2989> would suffice to enable std::is_specialization_of to be
> implemented as a library feature without such limitations. P2989
> is making its way through the committee process now (expected to
> be reviewed in EWG pending a new revision by its authors).
>
> Tom.
>
> On 11/19/23 9:34 PM, Paul Caprioli via
> Std-Proposals wrote:
>
> I'd like to float the idea of complex type traits, specifically `add_complex_t<T>`, `remove_complex_t<T>`, and the boolean `is_complex_v<T>`.
>
> Since a pointer to an element of an array of `std::complex<T>` can be reinterpreted as a pointer to `T` (with the real-valued array having twice as many elements), some codes use the former and others the latter. So, templated code in libraries and suchlike may want to work with either.
>
> My actual use case is FFTs, which can take real or complex arrays and real-valued scaling factors. The functions taking complex-valued arrays can accept `T*`. The scaling factor must be real, not complex. If you are curious about this in particular, my web page is https://hpkfft.com <https://hpkfft.com> and the type traits are here: https://hpkfft.com/hpk/complex_type_traits.html <https://hpkfft.com/hpk/complex_type_traits.html>
>
> Are these type traits generally useful enough for std? This question has nothing to do with FFTs.
>
> A motivating example might by `axpy()`, which multiplies the real-valued scalar `a` to each element of the array `x` and adds this to the array `y`. The array elements can be, say, `float` or `std::complex<float>`, but the scalar `a` has to be `float`. Note that the arrays can be arrays of real values or arrays of complex values, and if complex values, the type can still be `float*` with the understanding that the real and imaginary parts are interleaved. The same implementation works. If `a` were complex, then a different implementation would be needed.
>
> Regards,
> Paul
>
>

Received on 2023-11-27 21:33:27