On Wed, Nov 4, 2020 at 2:22 PM D'Alessandro, Luke K <ldalessa@iu.edu> wrote:
Hi Arthur,

On Nov 4, 2020, at 10:46 AM, Arthur O'Dwyer via Std-Proposals <std-proposals@lists.isocpp.org> 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