Récupérer une valeur aléatoire d'une énumération

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour à tous !

Imaginons que j'ai l'énumération suivante :

1
2
3
4
5
6
enum class Color
{
    red,
    green,
    blue
};

J'aimerais en récupérer une valeur aléatoire, mais je ne sais pas vraiment comment faire ça de manière élégante.

Que me conseillez vous ?

Merci :)

+0 -0

Tes enums sont des valeurs, puisque tu n'as pas préciser lesquelles il s'agit de 0, 1 et 2. Tu peux donc faire un random classique sur les int de 0 à 2 et caster le résultat en ton enum. Cette méthode pose plus de problème si tes valeurs ne se suivent pas (car il faut retirer si la valeur est interdite)

Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison - Coluche

+2 -0

Je ne vois aucune manière élégante de le faire.

ache.one                                                                                   🦊

+2 -0
1
2
3
4
5
6
7
8
enum class Color
{
    min,
    red,
    green,
    blue,
    max
};

Et tu fais un random entre min et max (non compris, évidemment). Si jamais tu ajoutes des valeurs à ton enum, prends bien garde à les mettre entre min et max, sinon ça ne marchera plus. Ca revient à peu près à ce que ceux du dessus ont dit.

+0 -0
Auteur du sujet

Désolé pour le temps de réponse, mais merci pour les votres ! :) Le problème de faire un random entre les valeurs d'une enum, c'est que je dois faire tout plein de cast de l'enum vers int, puis de int vers enum sinon le compilateur m'engueule… bref pas terrible quoi. (parce que j'ai une enum class et pas une simple enum si j'ai bien compris) De toute façon je suis pas fan des enumération, pas pour ce cas là en tout cas, du coup je l'ai laissé tomber

Je cherchais à modéliser des cartes générées aléatoirement et dont certaines propriétés dépendaient de la couleur, du coup j'ai mis tout ça dans une classe, et les différentes couleurs dans un vector. (pour le moment en tout cas…)

Je posterai d'ici une ou deux semaines le code complet dans un autre sujet pour avoir vos avis sur le code :)

Édité par Annyo

+0 -0

Lu'!

On peut avoir une classe comme ça :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
template<class T> T min();
template<class T> T max();

template<class Enum>
class uniform_enum_distribution : 
  private std::uniform_int_distribution<std::underlying_type_t<Enum>>
{
  static_assert(std::is_enum<Enum>::value, "Recieved type must be an enum type");

  using ut   = std::underlying_type_t<Enum>;
  using base = std::uniform_int_distribution<ut>;
  static constexpr Enum min = min<Enum>();
  static constexpr Enum max = max<Enum>();

  base& as_base(){ return static_cast<base&>(*this); }

public:
  constexpr uniform_enum_distribution() : 
    base(static_cast<ut>(min),static_cast<ut>(max))
  {}

  template<class URNG>
  auto operator()(URNG& g){
    return static_cast<Enum>(as_base()(g));
  }

  using base::reset;

  constexpr auto a() const{ return min; }
  constexpr auto b() const{ return max; }  
};

Et un usage comme ça :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
enum class Color : unsigned int{
  red,
  green,
  blue
};

template<>
constexpr Color min<Color>(){
  return Color::red;
}

template<>
constexpr Color max<Color>(){
  return Color::blue;
}


int main(){
    std::default_random_engine gen;
    uniform_enum_distribution<Color> ud{};

    for(unsigned i{}; i < 20; ++i){
      switch(ud(gen)){
      case Color::red   : std::cout<<"Color::red"<<std::endl; break;
      case Color::green : std::cout<<"Color::green"<<std::endl; break;
      case Color::blue  : std::cout<<"Color::blue"<<std::endl; break;
      default : std::cout<<"W00t ?"<<std::endl;
      }
    }
}

Notes :

  • je n'ai pas mis la fonction param et les constructeur correspondant à des sous-ensembles de l'enum car il ne me paraissent pas avoir vraiment de sens,
  • je ne passe pas par std::numeric_limits, car je ne crois pas que même avec un type sous-jacent entier, un enum class puisse répondre à la contrainte std::is_arithmetic demandé par la norme,
  • pas de trous, sinon c'est tout cassé et on ne peut pas le contrôler.

Édité par Ksass`Peuk

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+4 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte