/* 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