Selection of a valid random enumeration value in general form

Say we have an enumerated type E

 enum class E : underlying_type_of_E { v1 = uE1, v2 = uE2, //... vN = uEN }; typedef typename std::underlying_type<E>::type uE; 

In the general case, not all uE values ​​are valid values ​​of E , because we can choose a relation between them. Is there a general way to create random, real (named in the definition, not assigned) values ​​of E? This, for example, would not work:

 std::mt19937 m; std::uniform_int_distribution<uE> randomUE(0, std::numeric_limits<uE>::max()); E e = static_cast<E>( randomUE(m) ); 

because:

  • The range of values ​​may not start at 0
  • The range of values ​​may not end with std :: numeric_limits :: max ()
  • The range of values ​​may not be a range at all - we can select discrete values ​​for E from uE, for example {1, 3, 64, 272}.

Given that all of the listed values ​​are known at compile time, I cannot imagine why this would be dangerous or error prone.

As for the context, why I want this - I'm working on a genetic algorithm that uses a ratchet repository of verbs. At the moment, I use enumerations as chromosomes and save them in std::vector<bool> , which, upon request, is converted to std::vector<enumT> . The problem with this approach is a mutation that flips random bits with a given probability. This can cause problems, as it can lead to unacceptable chromosomes that do not indicate enum values.

+5
source share
1 answer

This can be done if you are ready to use the preprocessor macro to create the enum type and some metadata about it, but this is a minor problem:

  • Call the macro variable:

     ENUM(E, v1 = uE1, v2 = uE2, // ... vN = uEN); 
  • Create a templated Incrementing template where sequential variables are changed by default with the added static member, but can be assigned using any of your base types (like int ).

     static Incrementing<E, Underlying> __VA_ARGS__; \ 
  • Use the above values ​​to initialize an array with Incrementing values ​​(which need the operator Underlying() const member).

     static const Underlying values[] = { __VA_ARGS__ }; \ 

Then the values[] array contains the named values ​​of the enumeration ....

Here is the full version of this concept that I wrote many years ago here , but I would recommend just starting from scratch, considering your simple requirements.

+2
source

Source: https://habr.com/ru/post/1200565/


All Articles