2016-11-27 15 views
9

Czy istnieje sposób losowego wyboru elementu z wyliczenia w sposób bezpieczny dla typu?Losowo wybierz element z wyliczenia w sposób bezpieczny dla wersji z najnowszym C++

Najlepszym sposobem, aby to osiągnąć, jest wprowadzenie wartości terminatora jako ostatniego elementu wyliczenia, aby wiedzieć, ile jest wartości, a następnie wygenerować losową liczbę całkowitą w odpowiednim zakresie, który rzucić do enum. Ale wartość terminatora nic nie reprezentuje, więc masz nieważną wartość wyliczenia, a to nie jest bezpieczne. Czy istnieje lepszy sposób na to w najnowszych standardach C++?

+1

ciekawe pytanie, ale to wszystko sprowadza się do „istnieje uniwersalny typu bezpieczny sposób określania ilu wartości w enum?” , a odpowiedź na to, niestety, nie. Standardowym idiomem jest, jak wspomniałeś, uwzględnienie w wyliczeniu wartości wartownika, ale zgadzam się, że to jest brzydkie. Twoim jedynym rozwiązaniem byłoby napisanie niestandardowej klasy, która reprezentowałaby twoje wyliczenie, zapewniając jakąś niejawną konwersję, ale to prawie na pewno jest zbyt zaawansowane. Poza tym robi się gorzej, niż na pierwszy rzut oka wydaje się, że wartości w enumie nie muszą być liniowo rosnące; mogą występować skoki i nieciągłości. –

Odpowiedz

3

To wydaje się dobrym przypadku użytkowania na std::map

std::map<std::string, const int> nicer_enum {{"Do", 3}, {"Re", 6}, {"Mi", 9}}; 

std::cout << nicer_enum["Re"] << '\n'; // 6 

auto elem = nicer_enum.cbegin(); 
std::srand(std::time(nullptr)); 
std::advance(elem, std::rand() % nicer_enum.size()); 
std::cout << elem->second << '\n'; // 3, 6 or 9 

for (const auto &kv : nicer_enum) 
     std::cout << kv.first << ": " << kv.second << ' '; // Do: 3 Mi: 9 Re: 6 

std::cout << '\n'; 
+0

Nice! Ale byłoby lepiej, gdybyś użył '' i 'std :: string' zamiast technik pre-C++ 11. – Rakete1111

+0

Zgadzam się, ale nie chciałem odwracać uwagi od odpowiedniej części mojej odpowiedzi. (I tak na pewno nie powinno się zmieniać rozmiaru klawiszy mapy). –

+0

@RayHamel: Używanie 'const char *' * does * odwraca uwagę od odpowiedniej części odpowiedzi. –

Powiązane problemy