C++ Logo

std-proposals

Advanced search

Re: [External] std::to_array support for zero-length arrays

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 4 Nov 2020 14:54:02 -0500
On Wed, Nov 4, 2020 at 2:22 PM D'Alessandro, Luke K <ldalessa_at_[hidden]> wrote:

> Hi Arthur,
>
> On Nov 4, 2020, at 10:46 AM, Arthur O'Dwyer via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> If you're trying to use std::to_array with explicit template arguments, as
> in
> auto f3 = std::to_array<float>({1, 2, 3});
> auto f0 = std::to_array<float>({});
> then I think that usage needs justification (by which I actually mean, *that
> usage is wrong*).
>
> This is the use case that occurs with some frequency in real code, and is
> explicitly referenced numerous times in
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0325r3.html. I
> don’t feel like it is wrong.
>

I do. :)
I see it mentioned once in p0325r4's examples (but never called out as a
primary use-case), and zero times in the actual paper standard.

Right now, in most cases, the standard library reserves the right to replace
> template<class T, size_t N> auto to_array(T(&)[N]);
> with
> template<size_t N, class T> auto to_array(T(&)[N]);
> i.e. to alter "the number and order of deducible template parameters."
> When a library function has deducible parameters, you should always *let
> them be deduced*.
>
>
> This is a potential problem that I wasn’t aware of, thank you for pointing
> it out. Given p0325r3 maybe it is necessary to update the standard to make
> this a case where the order is constrained?
>

I believe the order *is* constrained in the current paper standard, for
this particular function template, because it's not currently found in
either of the big sections that that warning is applied to (STL algorithms
and Ranges utilities). However, it's not great to have two different rules
for explicit template arguments depending on which section of the standard
you happen to be reading. See also Jonathan Muller's "Trick 3" here:
https://foonathan.net/2020/10/tricks-default-template-argument/

> Why do you think you need this new overload? What use-case do you
> envision for "std::arrays of maybe zero length" that wouldn't be better
> solved with
> auto fn = std::array<float, sizeof...(args)>{ args... };
> ?
>
> Indeed, this is the current workaround we have implemented.
>

That's not a workaround! That's literally how you express "given this list
of initializers, construct me a std::array<float, sizeof...(args)>" in C++!
You don't need to instantiate a library function template to do it. (Btw,
instantiating a function template is one of the slowest things you can do
in C++, in terms of compile time cost, because it exercises the
code-generator and inliner.)
There's another nice advantage of the direct-initialization, which is that
it will do aggregate initialization when possible. If you call to_array,
you're generating two different copies of your data: one in a C array, and
then memcpying it into the std::array.

Perhaps my confusion is that to_array claims
>
> An interesting consequence of this proposal is that we no longer
> need make_array.
>
> I do not have any knowledge of the process that lead to the adoption of
> to_array and removal of make_array, however make_array _did_ support this
> usage and to_array does not without the overload.
>

My impression is that std::to_array({args...}) is a drop-in replacement for
std::experimental::make_array(args...). Neither std::to_array({}) nor
std::experimental::make_array() works today — it can't deduce the element
type `T`. Personally, I wouldn't call either of them with any number of
explicit template arguments.

Anyway, I would be mildly surprised if your code couldn't also benefit from
the advice in
https://quuxplusone.github.io/blog/2020/08/06/array-size/ ;)

–Arthur

Received on 2020-11-04 13:54:15