C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [C++ Proposal] Generic compile-time view

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Fri, 28 Jun 2024 19:12:40 -0500
On Thu, Jun 27, 2024 at 4:45 PM Omar Dooley via Std-Proposals <
std-proposals_at_[hidden]> 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

Received on 2024-06-29 00:12:53