Jak rzutować int na wyliczanie w C ++?

222

Jak rzutować int na wyliczenie w C ++?

Na przykład:

enum Test
{
    A, B
};

int a = 1;

Jak przekonwertować ana typ Test::A?

użytkownik1509260
źródło
1
link Zauważ, że nie ma znaczenia, czy int pasuje do jednej ze stałych typu wyliczeniowego; konwersja typu jest zawsze nielegalna.
Iwaz
3
Uważam, że jeśli chcesz rzutować na Test :: A, wartość int abędzie musiała wynosić 0, ponieważ Test :: A ma domyślną wartość 0, a Test :: B ma domyślną wartość 1. Chyba że fakt rzutowania specjalnie na Test :: A jest poza tym ...
JohnRDOrazio

Odpowiedzi:

243
int i = 1;
Test val = static_cast<Test>(i);
Andrzej
źródło
21
auto val = static_cast <Test> (i); // C ++ 11
Mitch
3
@Mitch Co dostanę za korzystanie autow tym przypadku? Czy są jakieś ulepszenia wydajności?
Frederico Pantuzza
2
Brak ulepszeń wydajności. Kompilator po prostu automatycznie dedukuje typ, jeśli określisz go jako „auto”. Jeśli zdecydujesz się zmienić nazwę wyliczenia w przyszłości, będziesz modyfikować swój kod mniej, ponieważ kompilator automatycznie wydedukuje poprawną nazwę typu.
Aydin Özcan
74
Test e = static_cast<Test>(1);
bames53
źródło
10
MSDN: Operator static_cast może jawnie przekonwertować wartość całkowitą na typ wyliczenia. Jeśli wartość typu całkowego nie mieści się w zakresie wartości wyliczenia, wynikowa wartość wyliczenia jest niezdefiniowana.
Kirill Kobelev
1
@KirillKobelev, jeśli wartość całki może być reprezentowana przez podstawowy typ wyliczenia, wówczas wyliczenie wynikowe musi mieć tę wartość. W przeciwnym razie wytworzona wartość wyliczenia będzie dowolną wartością wynikającą z konwersji wyrażenia na typ wyliczeniowy. Jeśli VC ++ robi coś innego, to uważam, że jest niezgodny.
bames53
2
co powinien zrobić kompilator zgodny, jeśli enum ma wartości {1,3,5}, a kod próbuje wykonać <cast_cast_tematyczny> od wartości 2. Czym to będzie różnić się od C-cast?
Kirill Kobelev
6
@KirillKobelev Nie używam static_cast, ponieważ robi on coś innego niż rzutowanie w stylu C, używam static_cast, ponieważ rzutowania C ++ są preferowane stylistycznie niż rzutowania C.
bames53
4
@KirillKobelev ”, jeśli wyliczenie ma wartości {1,3,5} " Nie. Typ wyliczenia nie może być ograniczony tylko do tych 3 możliwych wartości: {1,3,5} to wyliczacze (nazwane wartości wyliczeń), a nie same wyliczenia . Jeśli 1,3,5 są możliwymi wartościami wyliczenia , to również 2.
ciekawy
25

Twój kod

enum Test
{
    A, B
}

int a = 1;

Rozwiązanie

Test castEnum = static_cast<Test>(a);
użytkownik1515687
źródło
45
Dobrym pomysłem jest użycie najbardziej ograniczającej obsady i unikanie rzutów w stylu C, aby dać kompilatorowi najlepszą szansę na wykrycie błędów. static_castbyłoby lepiej obsady tutaj.
Mike Seymour
4
@Mike Seymour, problem polega na tym, że w tym przypadku obsada statyczna nie różni się od obsady C-cast. Jak i jaki błąd może wykryć?
Kirill Kobelev
7
@KirillKobelev: Problem polega na tym, że rzutowanie w stylu C nie jest jawne. Może być równy a static_cast, ale równie dobrze może być a const_castnawet gorzej, a reinterpret_castnawet ich kombinacją. Nawet jeśli wiesz teraz, co to ulegnie degradacji, załóżmy, że apóźniej zmienisz na inny typ, równie dobrze może to być rodzaj rzutowania zmian bez otrzymania ostrzeżenia, nie chcesz tego.
KillianDS,
4
@KillianDS „ załóżmy, że później zmienisz na inny typ ”, który to typ?
ciekawy,
2
Tak, te lub ukryta obsada, jeśli jest dostępna. Jest o wiele bardziej jasne, jakie są intencje obsady.
KillianDS,
8

Wydzielając końcowe pytanie: „jak przekonwertować typ na Test::A”, zamiast być sztywnym co do wymogu posiadania obsady , i odpowiadając kilka lat później, wydaje się, że jest to popularne pytanie, o którym nikt inny nie wspomniał o alternatywie , zgodnie ze standardem C ++ 11:

5.2.9 Obsada statyczna

... wyrażenie emoże zostać jawnie przekonwertowane na typ T przy użyciu static_castformularza, static_cast<T>(e)jeśli deklaracja T t(e);jest poprawnie uformowana, dla niektórych wynalezionych zmiennych tymczasowych t(8.5). Efekt takiej wyraźnej konwersji jest taki sam, jak wykonanie deklaracji i inicjalizacji, a następnie użycie zmiennej tymczasowej jako wyniku konwersji.

Dlatego bezpośrednie korzystanie z formularza t(e)będzie również działać i możesz go preferować ze względu na porządek:

auto result = Test(a);
Tommy
źródło
to rozwiązanie działało w przypadku, gdy opcja kompilatora została zablokowana static_cast <> (kontrola semantyczna). Nie to ma dla mnie sens, ale wciąż jest schludne.
Pan Buisson
1

Test castEnum = static_cast<Test>(a-1);rzuci a na A. Jeśli nie chcesz substrstratu 1, możesz przedefiniować enum:

enum Test
{
    A:1, B
};

W tym przypadku `Test castEnum = static_cast (a); ' może być użyty do rzutowania A na A.

kosolapyj
źródło