Witam.
Dlaczego w c++ w instrukcji switch nie można użyć innego typu niż typ całkowity, tak jak ma to miejsce w innych językach?
Bo tak postanowił autor języka.
W Javie dostępne "już od" wersji 7...
mozna uzyc innego typu niz integralny. Ktos nawet dawal tutaj ostatnio linka mysle ze to był @kq
ale pierwszy lepszy z googla
http://stackoverflow.com/questions/16388510/evaluate-a-string-with-a-switch-in-c
Tylko ze trzeba zrobic obudowe do tego.
w C++ mozesz zrobic co Ci sie jawnie podoba. Tylko ze musisz to przedtem zbudowac
fasadin napisał(a):
mozna uzyc innego typu niz integralny. Ktos nawet dawal tutaj ostatnio linka mysle ze to był @kq
ale pierwszy lepszy z googla
http://stackoverflow.com/questions/16388510/evaluate-a-string-with-a-switch-in-c
Tylko ze trzeba zrobic obudowe do tego.w C++ mozesz zrobic co Ci sie jawnie podoba. Tylko ze musisz to przedtem zbudowac
Tak: http://dev.krzaq.cc/switch-on-strings-with-c11/
Przy czym niestety to raczej zabawa z językiem a nie faktyczne rozwiązanie problemu. No ale jeśli jesteś pewien, że unikniesz kolizjii hasha (co jest kłopotliwe, bo ASCII/UTF-8 nie jest gwarantowane przez standard), to masz gwarancję, że to będzie działało poprawnie.
edit: switcha można całkiem skutecznie zasymulować kontenerem par predykat-funkcja, gdzie wykonywana jest funkcja, jeśli predykat jest prawdziwy.
A co do odpowiedzi na zadane pytanie:
- jeśli mówimy o string literalsach - to są to po prostu tablice
T const[S]
, gdzieT
to typ znaku zależny od definicji, aS
to długość stringa + 1. Tablic w C i C++ nie można porównywać za pomocą=
, więc zapewne z tego powodu nie mogą być wyrażeniami w switchu. - jeśli mówimy o
std::string
to jest to "zwykła" klasa i nic poza przestrzenią nazw nie różni jej od czegoś co możesz zdefiniować sam. Wobec tego należałoby rozszerzyć pytanie do "dlaczego nie wolno używać własnych typów w switchu". Przed C++11 odpowiedzią na to pytanie było "nie można zainicjalizować klasy w czasie kompilacji". Od C++11 mamyconstexpr
i w sumie nie wiem dlaczego ta restrykcja została. Być może nikt o to dostatecznie głośno nie walczył? Być może chodzi o to, że kompilator nie jest w stanie dowieść, żeoperator==
Twojej klasy nie zwrócitrue
dla kilkucase
'ów?
kq napisał(a):
- jeśli mówimy o
std::string
to jest to "zwykła" klasa i nic poza przestrzenią nazw nie różni jej od czegoś co możesz zdefiniować sam. Wobec tego należałoby rozszerzyć pytanie do "dlaczego nie wolno używać własnych typów w switchu". Przed C++11 odpowiedzią na to pytanie było "nie można zainicjalizować klasy w czasie kompilacji". Od C++11 mamyconstexpr
i w sumie nie wiem dlaczego ta restrykcja została. Być może nikt o to dostatecznie głośno nie walczył? Być może chodzi o to, że kompilator nie jest w stanie dowieść, żeoperator==
Twojej klasy nie zwrócitrue
dla kilkucase
'ów?
Tak, właśnie miałem na myśli własne typy.
Trochę nie rozumiem tego: "nie można zainicjalizować klasy w czasie kompilacji".
Skoro jest możliwe coś takiego:
if(obj == obj2)...
to dlaczego nie można zrobić tego tak?:
switch(obj){ case ob2:...
Oczywiście, w przypadku porównywania obiektów, trzeba by było wywołać metodę, która by te obiekty porównała, a potem wykonać skok, ale co to za problem? switch jest czymś innym, niż zwykłym skokiem warunkowym, takim jak if?
Warunki case
'ów muszą być stałe w czasie kompilacji, inaczej ryzykujesz masakryczną niewydajność. Weź na przykład klasę Matrix
reprezentującą macierz. Czy
case Matrix::ones(1000,1000):
powinno alokować kilka MB tylko do porównania jednego z wielu warunków? A co jeśli konstruktor wpływa na jakiś stan globalny? Ponadto jeszcze jest zasada unikalności wartości w case
'ach - co zrobić, jeśli operator=
Twojego typu jest zależny od jakiejś zmiennej globalnej? Pamiętaj, że program kompilowany jest jedno TU naraz i kompilator nie widzi większości definicji.
tl;dr: twórcy postanowili, że switch
będzie miał takie ograniczenia, i zgodnie z nimi nie można łatwo switchować po dowolnym typie.
Zawsze możesz coś takiego zrobić:
http://ideone.com/6nQWsX