On Thu, Jun 27, 2024 at 4:45 PM Omar Dooley via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
/* It's easy to make an array of uniquely sized compile-time strings: */
[snip: std::array<std::string_view> of string literals]

/* This is possible because after all they're just pointers (to an array of chars), 
 * but where is this flexibility for other (trivial[?]) types? std::chrono::duration,
 * int, float, bool, [user-defined] ...
[...] 
/* using an std::initializer_list is very close, but this approach betrays it's
 * intended use, and not to mention it's undefined behavior and/or ill-formed -
 * even with (P2752R1) "Static storage for braced initializers" 
 */

using init_list = std::initializer_list<milliseconds>;
constinit std::array<init_list, 3> arr {
    { 32ms, 3ms, 18ms, 123ms },
    { 2ms, 86ms },
    { 40ms, 12ms, 92ms }
};

Correct, P2752 left this as UB. (Source: I'm the author of that paper, which was accepted and is expected to be DR'ed back to all versions of C++ by all compiler vendors, as far as I know.) But there's no super great reason for it to be UB. I certainly wouldn't vote against a well-designed proposal to make all the things that Just Work in practice, also Just Work in theory. The trick is the "well-designed": can you come up with a good mental model for how initializer_lists work, given that they can view an array of compile-time constants or view a temporary array of non-constants? That's the tricky bit.


/* Thus I'm proposing a generic, compile-time view (std::generic_view[?]) for
 * the added flexibility it provides. It would have the written semantics of a
 * std::string_view but is not exclusive to char types.
 *
 * There should be a simple means of expressing sequences of arbitrary data in
 * string-like fashion without the size specification constraints of arrays and
 * the allocation of vector.
 */

/* Example Use 1 */
constinit 
std::array<std::generic_view<int>, 4> arr {
    {1, 4, 2, 6, 7},
    {9, 3, 6},
    {6, 2, 0, 1},
    {3, 7}
};

You are describing one of these three possibilities:
exactly `std::initializer_list` (with the UB solved),
- a class type `generic_view` with an initializer-list constructor,
- a second magic builtin type which works exactly like `std::initializer_list` except that it solves the UB that `initializer_list` hasn't solved yet.
There's not much difference between option #3 and option #1.
Option #2 is just option #1 with extra steps: you still have to solve the UB problem of `initializer_list`, if it is going to form part of your solution.

Also, if you went with option #2: How would your proposed `generic_view<T>` differ at all from C++20 `span<T>`?

So I encourage you to try to figure out how to solve the UB in option #1. I think that's not only more elegant than any additional-class-type or additional-magic-type option; it's actually the only way that makes sense, because the additional-class-type and additional-magic-type options are just the initializer_list option with extra steps.

my $.02,
Arthur