W C++ typy wyliczeniowe deklaruje się zwykle poprzez coś podobnego do poniższego kawałka kodu:
Jego skutkiem jest jednak to, że nazwy stałych typu (tutaj: Left
, Middle
i Right
) będą widoczne w całej przestrzeni nazw zawierającej daną deklarację enum
. Jeśli więc przypadkiem jest ona globalna, to całkiem łatwo może ona spowodować konflikt chociażby z innym typem w rodzaju:
Aby zapobiegać takim sytuacjom, w Javie i C# stałe wyliczeniowe muszą być kwalifikowane nazwą odpowiedniego typu – używa się więc Sides.Left
i Keys.Left
. W C++ jest jednak inaczej, gdyż blok enum
sam w sobie nie tworzy zasięgu (w przeciwieństwie np. do bloków class
).
Można temu częściowo zaradzić w następujący sposób:
dzięki czemu możemy z naszego enum
a korzystać tak:
Różnica względem wspomnianych dwóch języków polega na tym, że nazwa typu wyliczeniowego (Side
) oraz kwalifikator stałych (Sides
) nie są takie same. Wydaje się jednak (przynajmniej mi się tak wydaje :]), że w tym przypadku takie rozróżnienie jest logicznie poprawne i wygląda nawet czytelniej niż gdyby obie nazwy były identyczne.
Trik ten można naturalnie opakować w makro, które umożliwi łatwe tworzenie typów wyliczeniowych z kwalifikowanymi nazwami stałych. Nie poprawi to oczywiście funkcjonalności enum
ów w C++, ale przynajmniej sprawi, że będą ładniej wyglądały :D
Hm, może jest późno, ale nie rozumiem chyba dlaczego jest
foo = Sides::Left;
a nie
foo = Side::Left;
Jest wcześnie i też się zastanawiam :s
aaa: Ponieważ Side to typedef na Sides::_Enum, a używamy Sides::Left a nie Sides::_Enum::Left :P
a ja od razu skumałem :P
Dodajmy jeszcze, ze nazwy zaczynajace sie podkresleniem + duza litera sa zarezerwowane dla kompilatora, wiec technicznie Sides::_Enum lamie zgodnosc ze standardem :) Sides::Enum bedzie OK. Wiecej – http://powerof2games.com/node/30
ale można łatwiej
Wtedy rzeczywiście piszemy S::E0, S::E1, itd., ale nie da się w ogóle stworzyć zmiennej należącego do tego typu wyliczeniowego. Bo
nią nie będzie.
yarpen: Zawsze myślałem, że dotyczy to tylko nazw z dwoma podkreśleniami na początku i niekoniecznie z wielką literą potem (przykład: __cplusplus). Możesz podać jakieś źródło tej informacji? (Oczywiście najlepiej odpowiedni punkt standardu :D).
[up] no racja ale…(hehe zawsze jest jakieś ale:p)
i już możemy sobie zrobić:)
USO 14882:2003, 17.4.3.1.2, pierwszy myślnik: Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase
letter (2.11) is reserved to the implementation for any use.
argh. ISO oczywiście :)