On Fri, 24 Jun 2022 at 02:01, Hadriel Kaplan
On Thursday, June 23, 2022, 05:20:01 PM EDT, Richard Hodges via Boost < boost@lists.boost.org> wrote:
Yes, I'm looking for a real-world use case. The trivial hypothetical cases offered are building a static association between an enum value and some other value. This can be done with switch/case (for example), in about the same amount of typing, at compile time, in a function.
<snipped example switch-case code>
OK, now show me how to iterate over it. And how to get a view or slice of it (i.e., std::span or range). And how to get the number of elements. :)
I understand that presenting the type with the look and feel of a container is somehow pleasing. The ability might be an interesting academic goal. I am more interested in what real-world use-cases this solves. boost.describe, wise_enum etc solve the case where (for example) I wish to serialise and deserialise my enum value as text. This is useful in the real world as, for example, it allows me to easily and reliably implement a JSON communications protocol that contains my enum. Indexed array still has the maintenance burden of having to maintain both the enum and the associative "array" separately.
I mean ultimately, it's a container. It's not _only_ useful for key'ed lookup retrieval.
You can change the value of whatever the container holds too, for example. Or maybe I'm misunderstanding your point? (could easily be the case)
Anyway, the main use-case or value of it, in my mind anyway, is actually the one when using Boost.Describe. Because when you're using Describe for an enum, you only need to do this for indexed_array:
indexed_array
data; That's powerful, because you do not need to repeat any code, do not need to repeat any sizing/number of enums, etc. If you add new enumerators to your enum, you don't need to change this instantiation of indexed_array. It's all automatic, and you can't screw up.
The arbitrary intervals and non-contiguous use-cases I'm less convinced by. It's too easy to mess up.
And arguably it's not really a "indexed_array" at that point anyway - the underlying container might happen to be a std::array, but that's an implementation detail. From the user's perspective it's more like a "static_map" or some such. Except... it's not actually necessarily sorted, is it? All the examples show them sorted, but I'm not sure it really is if the user doesn't define it that way? (I'm trying _not_ to read the code - only the docs)
Perhaps there is a case when seeking to parse a number of flags that are presented as text and each flag may not appear more than once? enum class NerfEnum : char { wounded = 'W', buffed = 'B'; burning = 'N'; }; BOOST_DESCRIBE_ENUM(NerfEnum, (wounded, buffed, burning)); JSON input: { ... "nerfs": [wounded, buffed, burning] ... } indexed_array might then be used to efficiently store the set of flags associated with this unfortunate character. But in this case, am I not better off with an unsigned int, where each flag is represented by a bit? The "natural code" might be: unsigned flags = 0; for(auto&& value : nerfsjson.as_array()) flags |= to_bit(*deserialise<NerfEnum>(value.as_string()); I could imagine that being able to express this bitset with a container-like interface might make my code more intuitive, but I don't think that indexed_array addresses this case. (I appreciate that such a container would have some of the same criticisms of vector<bool>)
-hadriel