On Sun, Sep 25, 2022 at 11:55 AM Edward Catmur <ecatmur@googlemail.com> wrote:
>
> (re-adding list; hope this is OK)
>
> On Sun, 25 Sept 2022 at 16:34, Jason McKesson <jmckesson@gmail.com> wrote:
>>
>> > I'm not sure we could agree on what we want. Enums can be empty, or forward declared (with an underlying type); the range of enumerators may be those named, or it may be those named less sentinel values, or it may be some arithmetic closure of the named enumerators (e.g. for enumerations with bitwise operations).
>> >
>> > The only way to handle all of these is with reflection (over the named enumerators, and possibly metadata).
>>
>> Your argument is structurally equivalent to the argument that, because
>> some people want to have a vector-like type that has a hard cap on its
>> allocation size or always uses a built-in buffer, we shouldn't have
>> `std::vector` since it cannot cover all of those cases. No, `vector`
>> is legitimately useful to actual users even though it's not useful for
>> everyone.
>>
>> The same goes here; basic high-level tools don't have to handle every
>> single case. Remove all the cases where a user wants to only consider
>> *some* enumerators (ie: sentinels), and we can come to an agreement
>> pretty quickly on what those tools ought to be.
>>
>> Fear of not being able to help everyone should not stop us from helping someone.
>
>
> I don't think the analogy holds. OP was already requesting density statistics, so it's questionable whether min() and max() even constitute a MVP.
>
> But also, `<vector>` standardized existing practice, and didn't prevent people writing their own contiguous containers with specialized semantics. (Uh, other than the array problem, which isn't an issue in practice, since compiler vendors know to DTRT.) Given reflection, library authors (Boost.TypeTraits, e.g.) can settle on an appropriate collection of statistics and then the Standard can provide them once practice is established.
>
> Our experience (using Boost.Describe for reflection) is that some of the time min() and max(), plus bool dense(), are sufficient. But often we also want to list the enumerators, sort them, uniquify, name, validate, lift from runtime to compile time, etc. I really don't think we'll know what is appropriate without experience of reflection proper.
That kind of thinking, where you have to do everything if you want to
do anything, is exactly the kind of thinking that prevents *anything*
from getting done.
"Wait for reflection" is a fool's errand. We should have enumeration
tools now; they can be implemented in reflection once that's done. But
there's plenty of established practice out for what users need that we
can cull from.
So long as the tools are not actually doing reflection (ie: allowing
users to directly iterate over enumerators and their values), they
should be considered as a distinct construct from reflection.
The most basic set of operations that don't actually do reflection would be:
Compile-time properties of an enumeration:
* The minimum/maximum enumerator values.
* Is dense (no gaps at any point in the enum).
* Are all values unique (no repeated enumerator values)?
>From compile-time values:
* Is this value within the set of values for the enumerators?
* Does this value (which conforms to the above) uniquely identify a
single enumerator?
* Give me a string literal which names the enumerator uniquely
identified by this value.
>From runtime-values:
* Is this value within the set of values for the enumerators?
* Does this value (which conforms to the above) uniquely identify a
single enumerator?
* Give me a string literal which names the enumerator uniquely
identified by this value.
Note that the latter interfaces should make it painfully obvious to
the user that they require runtime storage. Not dynamically allocated
of course, but that by asking these questions they are adding to their
binary's size. For example, they could be built into some `inline
constexpr` variable template, accessed through non-static member
functions.
Yes, that sounds sufficient for most use cases; and there's daylight between that and full reflection, e.g. declaration order of enumerators, non-unique enumerators. I'd support that if it would arrive sooner than reflection.