|
#16
|
|
|
|
|
Witam
> Odpowiedź jest prosta. Po prostu się nie da. Trudno mi sobie > nawet takie coś wyobrazić. E tam. Że odrazu sie nie da. Kwestia ceny. virtual boost::any do_foo (boost::any); lub pobierajac DynamicAny i zwracajac rowniez. virtual DynamicAny do_foo (DynamicAny); To jest totalna wolna amerykanka. Oczywiscie uznaje to jako pewna luke w projekcie, ale są pewne wyjatki. Np. jakis parser moze zwracac dialbli wiedza co. I tam mozna zaimplementowac kontekstowe wolanie type value = cast<type>(foo()); Szczegolnie to dotyczy typow prostych, ktorych liczba jest ograniczona jednak sa na tyle roznorakie, ze zrobienie dla nich klasy bazowej nie jest eleganckie. >Każde nowe "zrób ogólne foo()" > wymagałoby zmiany we wszystkich klasach pochodnych. To to > już całkowicie łamie zasadę open-close. Tak. Pozdrawiam, Seweryn Habdank-Wojewódzki. |
|
|
|
#17
|
|
|
|
|
Krzysiek Kowaliczek <this> wrote:
> void foo () > { > const Expression& e = getExpression (); > switch ( e ) > { > case BinaryExpression x: > break; > case UnaryExpression x: > break; > case NumberExpression x: > break; > }; > } const Expression& e = getExpression (); const std::typeinfo& te = typeid(e); if (te == typeid(BinaryExpression)) ; else if (te == typeid(UnaryExpression)) ; else if (te == typeid(NumberExpression)) ; nieeleganckie, ale glównie dlatego ze tu powinno sie zastosowac zwykly polimorfizm. B. |
|
#18
|
|
|
|
|
On Thu, 26 Jun 2008 23:54:01 -0700 (PDT), Seweryn Habdank-Wojewódzki
<habdank> wrote: [..] >DynamicAny any("42"); >int i = any; // i == 42 >any = 65536; >std::string s = any; // s == "65536" > >// mozna tez dodac jeszcze takie cos: >char c = any; // too big, throws RangeException > >Tego powyzej nie umiem napisac w Pythonie jak ktos potrafi to prosze o >uzupelnienie. Co swiadczy dobrze o Pythonie A.L. |
|
#19
|
|
|
|
|
In the darkest hour on Fri, 27 Jun 2008 10:47:07 -0700 (PDT),
Seweryn Habdank-Wojewódzki <habdank> screamed: > >> > c = chr(any) // rowniez sypnie wyjatkiem >> >>> c = unichr(any) >> >>> c >> >> u'\uffff' > > Tak. Ale to, ze tamto powyzej sypie wyjatkiem jest bardzo dobre. > Python ma sypnac bledem, bo glupio robie. > To też wcale tak nie twierdziłem. ;) |
|
#20
|
|
|
|
|
Bronek Kozicki wrote:
> const Expression& e = getExpression (); > > const std::typeinfo& te = typeid(e); > if (te == typeid(BinaryExpression)) > ; > else if (te == typeid(UnaryExpression)) > ; > else if (te == typeid(NumberExpression)) > ; > No wlaśnie, to tylko pólśrodki. Chcialbym dostac ostrzezenie lub bląd jezeli dodam nową podklase Expression. Przykladowo, mam taki oto kod w ocamlu: type expression = | BinaryExpression | UnaryExpression | NumberExpression let process expr = match expr with | BinaryExpression-> 1 | UnaryExpression-> 2 | NumberExpression-> 2 let _ = print_int ( process BinaryExpression ) Jezeli rozbuduje typ expression o powiedzmy StringExpression to przy kompilacji dostane ostrzezenie: File "test.ml", line 8, characters 2-94: Warning P: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: StringExpression Najbardziej podoba mi sie wersja dla Scali: http://www.scala-lang.org/intro/caseclasses.html Podsumowywując: bylem ciekaw jak sobie radzicie w podobnych przypadkach. Ja chetnie zobaczylbym konstrukcje znane z jezyków funkcjonalnych, w C++. Obecnie bardziej sklaniam sie ku rozwiązaniu jakie zaproponowal Witek ( plus ewentualna statyczna asercja ), zamiast wzorca wizytor. Pozdrawiam KK |
|
#21
|
|
|
|
|
Witam
> >// mozna tez dodac jeszcze takie cos: > >char c = any; // too big, throws RangeException > > >Tego powyzej nie umiem napisac w Pythonie jak ktos potrafi to prosze o > >uzupelnienie. > > Co swiadczy dobrze o Pythonie Drogi Panie A.L. spóźnił się, Pan, bo już pojawił się mój post z uzupełnieniem. Nie wiem, co dobrze świadczy o pythonie, ale to coś już zniknęło, jeżeli wynikało tylko z faktu, że przez 15 minut nie umiałem tego napisać. To już sie stało. Przykro mi. Już nie ma tego czegoś co dobrze świadczy o Pythonie. Są inne rzeczy, ale nie ta, Pozdrawiam, Seweryn Habdank-Wojewódzki. |
|
#22
|
|
|
|
|
Witam
> No właśnie, to tylko półśrodki. Chciałbym dostać ostrzeżenie > lub błąd jeżeli dodam nową podklasę Expression. Czemu nie uzyc dynamic_cast? dynamic_cast jak sobie nie radzi rzuca wyjatek. > Najbardziej podoba mi się wersja dla Scali:[..] A tak a propos Scali. Jaka jest jej wartosc dodana tego jezyka wzgledem Pythona? Pozdrawiam, Seweryn Habdank-Wojewodzki. |
|
#23
|
|
|
|
|
Seweryn Habdank-Wojewódzki wrote:
> Czemu nie uzyc dynamic_cast? > dynamic_cast jak sobie nie radzi rzuca wyjatek. Nie przeczytałeś dokładnie: chcę mieć taką informację w trakcie kompilacji. Skoro mam język statycznie typizowany, to chciałbym w pełni to wykorzystać. > A tak a propos Scali. Jaka jest jej wartosc dodana tego jezyka > wzgledem Pythona? > Scala to nie jest Python inaczej. Scala jest statycznie typizowana, więc nie ma sensu bezpośrednio ich porównywać. Pozdrawiam KK |
|
#24
|
|
|
|
|
Witam
> Nie przeczytałeś dokładnie: chcę mieć taką informację w > trakcie kompilacji. Skoro mam język statycznie typizowany, > to chciałbym w pełni to wykorzystać. Hmm... no to static_cast? Ewentualnie w brzydkiej wersji reinterpret_cast jesli jestes pewien, ze to co rzutujesz to jest to co chcesz miec. > > A tak a propos Scali. Jaka jest jej wartosc dodana tego jezyka > > wzgledem Pythona? > > Scala to nie jest Python inaczej. Skadnia jest jakby rrznieta z Pythona. > Scala jest statycznie > typizowana, więc nie ma sensu bezpośrednio ich porównywać. Hmm... na tej grupie sa spece od porownywania: C++ i Lispa, C++ i Pythona, C++ i VB itd. Wiec czemu mielibysmy oszczedzic Scale? :-) A poza statyczna typizacja czy jest cos super? Pozdrawiam, Seweryn Habdank-Wojewodzki. |
|
#25
|
|
|
|
|
On 1 Lip, 16:56, Seweryn Habdank-Wojewódzki <habd> wrote:
> > Nie przeczytałeś dokładnie: chcę mieć taką informację w > > trakcie kompilacji. Skoro mam język statycznie typizowany, > > to chciałbym w pełni to wykorzystać. > > Hmm... no to static_cast? Ewentualnie w brzydkiej wersji > reinterpret_cast jesli jestes pewien, ze to co rzutujesz to jest > to co chcesz miec. Informację w czasie kompilacji, czyli komunikat kompilatora, jeśli nie wszystkie przypadki zostały obsłużone. static_cast w niczym tu nie pomoże, a tym bardziej reinterpret_cast (który w ogóle nie zadziała przy wielodziedziczeniu, a i przy pojedynczym dziedziczeniu nie chce mi się sprawdzać, czy musi). |
|
#26
|
|
|
|
|
Witam
> Nie przeczytałeś dokładnie: chcę mieć taką informację w > trakcie kompilacji. Skoro mam język statycznie typizowany, > to chciałbym w pełni to wykorzystać. Ponizej zamieszczam pewien kod. Zawsze klasa dziedzicona z base musi miec metode do_get_class_id. A zatem jak tego nie napiszesz kompilator obrzuci Cie błotem. Co wiecej klasa Derived_3 jest celowo zakomentowana. Bo tez sie nie kompiluje -- specjalnie nadalem jej ID, ktore pokrywa sie z 2. Wchodzac do switcha mozesz wziac ID klasy, jest ono unikalne dzieki spomnianemu ficzerowi, bo nie unikalne ID nie kompiluje sie. Jesli to nie jest to o co Ci chodzi to nie rozumiem o co w ogole chodzi :-). Pozdrawiam, Seweryn Habdank-Wojewodzki. #include <iostream> #include <memory> using namespace std; template <int id> class Class_ID { public: enum {ID = id}; }; class Base { public: typedef Class_ID<0> CID; Base() {} virtual ~Base(){} int const get_class_id() const { return do_get_class_id(); } private: virtual int const do_get_class_id () const { return CID::ID; } }; class Derived_1 : public Base { public: typedef Class_ID<1> CID; Derived_1() {} virtual ~Derived_1(){} private: virtual int const do_get_class_id () const { return CID::ID; } }; class Derived_2 : public Base { public: typedef Class_ID<2> CID; Derived_2() {} virtual ~Derived_2(){} private: virtual int const do_get_class_id () const { return CID::ID; } }; /*class Derived_3 : public Base { public: typedef Class_ID<2> CID; Derived_3() {} virtual ~Derived_3(){} private: virtual int const do_get_class_id () const { return CID::ID; } };*/ void fun (Base & b) { switch(b.get_class_id()) { case Base::CID::ID: cout << "0\n"; break; case Derived_1::CID::ID: cout << "1\n"; break; case Derived_2::CID::ID: cout << "2\n"; break; //case Derived_3::CID::ID: //cout << "3\n"; break; } } int main() { typedef auto_ptr <Base> Base_ptr; Base_ptr p (new Base); fun (*p); p = Base_ptr (new Derived_1); fun (*p); p = Base_ptr (new Derived_2); fun (*p); } |
|
#27
|
|
|
|
|
Seweryn Habdank-Wojewódzki wrote:
> Ponizej zamieszczam pewien kod. Zawsze klasa dziedzicona z base > musi miec metode do_get_class_id. A zatem jak tego nie napiszesz > kompilator > obrzuci Cie błotem. Co wiecej klasa Derived_3 jest celowo > zakomentowana. > Bo tez sie nie kompiluje -- specjalnie nadalem jej ID, ktore pokrywa > sie z 2. > Wchodzac do switcha mozesz wziac ID klasy, jest ono unikalne dzieki > spomnianemu ficzerowi, bo nie unikalne ID nie kompiluje sie. > Ech, Qrczak Ci przecież już napisał. Nie chodzi mi o możliwość nadawania unikalnego identyfikatora bo i po co. Chodzi mi o to, że jak dodam Derived_3, ale nie obsłużę jej w kodzie to chciałbym dostać błąd: // dodałem nową klasę class Derived_3 : public Base .... dalej w kodzie mam: void fun (Base & b) { switch(b.get_class_id()) { case Derived_1: cout << "1\n"; break; case Derived_2: cout << "2\n"; break; // <-- tutaj powinno być case Derived_3: } } // dalej jeszcza x podobnych przypadków jak w fun I właśnie w funkcji fun chciałbym, aby kompilator poczęstował mnie błędem. Podobnie jak Maciek (*) zastanawiałem się jak obsłużyć takie przypadki. I wyszło mi, że najlepszy byłby sposób znany np. z ocaml ( chociaż tam dopasowanie do wzorca ma dużo, dużo większe możliwości niż prosty switch z c++ ). Zastanawiałem się czy inni grupowicze, odczuwali potrzebę takiej konstrukcji w C++. Ewentualnie ktoś coś może słyszał, że były takie propozycje w przyszłej wersji standardu. Ale wychodzi na to, że swich + enum, ewentualnie wzorzec wizytor wszystkim wystarcza :), ponieważ nie było żadnych głosów poparcia. (*) http://www.inspirel.com/articles/Visitor_Revisited.html Pozdrawiam KK |
|
#28
|
|
|
|
|
Seweryn Habdank-Wojewódzki wrote:
> Hmm... no to static_cast? Ewentualnie w brzydkiej wersji > reinterpret_cast jesli jestes pewien, ze to co rzutujesz to jest > to co chcesz miec. > Patrz odpowiedź Qrczaka. > Skadnia jest jakby rrznieta z Pythona. > Żarty chyba sobie stroisz. Ja tam podobieństwa nie widzę. > Hmm... na tej grupie sa spece od porownywania: > C++ i Lispa, C++ i Pythona, C++ i VB itd. > > Wiec czemu mielibysmy oszczedzic Scale? :-) Z tego co napisałeś, zrozumiałem, że Scala to klon Pythona. Tak jak już pisałem Scala to nie jest Python zrobiony lepiej, więc w ten sposób nie ma sensu ich porównywać. > > A poza statyczna typizacja czy jest cos super? > Scala to scyzoryk szwajcarski. Każdy znajdzie tutaj coś dla siebie, łączy zalety programowania obiektowego i funkcjonalnego ( http://www.scala-lang.org/intro/index.html ). Poza tym to jedyny sensowny język na JavaVM ;). Pozdrawiam KK |
|
#29
|
|
|
|
|
Witam
> Żarty chyba sobie stroisz. Ja tam podobieństwa nie widzę. Kwestia miary :-). > Z tego co napisałeś, zrozumiałem, że Scala to klon Pythona. Klon, to nie, ale idea jest mocno zaczerpnięta z Pythona. > Tak jak już pisałem Scala to nie jest Python zrobiony > lepiej, więc w ten sposób nie ma sensu ich porównywać. Hmm... a ja myślałem, że można, tak samo jak można porownywać C++ do Ocalma. > Scala to scyzoryk szwajcarski. Nie widze tego tak rozowo. Jakby tak było nikt by nie pisal ani w Javie ani w J(P)ythonie. Oczywiscie nie zabraniam nikomu sie bawic w pisanie jakiegokolwiek jezyka. Moze nawet Scala bedzie miala wiecej userow niz kazdy dedykowany jezyk, ale osobiscie nie widze, aby byl lepszy od Pythona. Nawet jesli jest taki sam, pomijając typizację, to naprawdę nie widze silnej przewagi. Rozumiem, że Scala probuje naprawic bledy w Javie jako takiej, ale to IMHO za malo. Tym bardziej, żę kod z Pythona przenosi się na Jythona, a zatem jest mocno nie zalezy zarowno od systemu jak i od VM. Scala, coz, tylko JVM. > Poza tym to jedyny sensowny język na JavaVM ;). Kiedys uczestniczylem w dyskusji, w ktorej to samo mowiono o Groovym. Groovy ma skladnie rowniez podobna do Pythona. Jest dynamiczny. Groovy jest u mnie w rankingu jeszcze dalej niz scala. Pozdrawiam, Seweryn Habdank-Wojewódzki. |
|
#30
|
|
|
|
|
Witam
> Chodzi mi o to, że jak dodam Derived_3, ale nie obsłużę jej > w kodzie to chciałbym dostać błąd: > // dodałem nową klasę > class Derived_3 : public Base Nie bardzo widze, aby to miało globalny sens. Pomyśl. Jest aplikacja i masz jakąś klasę bazową A. Ludzie obługują tylko A, B i C w 1000 miejscach w kodzie. B i C dziedziczą po A. Teraz dopisuję klasę D w jakimś odległym miejscu. I co? Są problemy. 1. Skąd kompilator ma wiedzieć ze w jakims moim headerze niekoniecznie inkludowanym jest klasa D. 2. Nawet jesli includuje klasę D, to dlaczego projekt ma sie nie kompilowac w 1000 miejscach, bo ja sobie napisalem klasę D. Pomysl tak: masz 10 koderow kazdy co tydzien dziedziczy jakas klase z jakiejs innej (takiej powodujacej błędy). Sama obecnosc nowej klasy bedzie wywalac kompilacje. Tego nigdy nie naprawisz. Musisz miec mozliwosc, aby one były obecne w kodzie ale nie dzialajace. Co wiecej masz wersję release w ktorej za nic w swiecie nie chcesz wlaczac klas nowych. One moga byc tylko w wersji debug lub test. Zatem potrzebujesz miec mechanizm rejestracji klas uzytkowych w zaleznosci od wersji. Poza tym wcale nie jest powiedziane, ze w kazdym z 1000 miejsc, w ktorych masz "switch", jest tak naprawdę gotowy przyjac nowa klase. Czasami chcesz obsłuzyc tylko te, ktore sa wymienione zadne inne. Więc taki automat raczej by mi szkodzil niz pomagał. 3. Jesli zatem musisz klase rejestrowac w czasie kompilacji, to czemu nie uzyc, tego co język OFERUJE, np. listy typów, szerzej o tym w kontekście wizytatora pisze Alexandrescu. Moze jego rozwiazanie nie jest idealne, ale jak ktos bedzie mial dokladna specyfikacje o co mu chodzi, to moze sobie to podejscie poprawic na swoja modle. W każdym razie ja jestem przeciwny wprowdzania automatow, ktore moga mi szkodzic. Jesli bede chcial miec blad to poprosze o to, ale nie domyslnie. > dalej w kodzie mam: ... > case Derived_2: > cout << "2\n"; break; > // <-- tutaj powinno być case Derived_3: Po co? Skąd wiesz, że ja w ogole chcę obsłużyć w tym miesjcu nową klasę. Może nie jestem gotowy. Może NIGDY tego nie zrobię. Pomyśl masz wzorzec strategia zawierający jakies algorytmy. Ale one są w ogólnej bibliotece. A ja chcę miec tylko 2 znich (np. z 10). Dlaczego mam produkować 8 pustych case takich: case Derived_3: break; case Derived_4: break; case Derived_4: break; case Derived_5: break; ... case Derived_8: break; Hmm? Nie widzę sensu. > I właśnie w funkcji fun chciałbym, aby kompilator > poczęstował mnie błędem. Jeszcze raz mówię, pomyśl globalnie. 10 koderów, każdy tydzień nowa klasa (to jest i tak bardzo wolno). Ale powiedzmy, że raz na tydzień masz klasę dziedziczoną z takiego cuda, co powoduje niekompilowanie się kodu. Teraz dorzucasz wersję debug, test i release, gdzie w release nie masz niczego co naprawdę nie sprawdziłeś. I po ostatnie. Masz miejsca gdzie celowo obsługujsze tylko dwie klasy. Jak to zrobisz? > Podobnie jak Maciek (*) zastanawiałem się jak obsłużyć takie > przypadki. I wyszło mi, że najlepszy byłby sposób znany np. > z ocaml Może. Mnie ten język iteresuje hobbistycznie do 100 lini kodu -- nie widzę problemów o których piszę. Dynamicznie rozwijajacego sie kodu powyzej 100 000 lini nie widziałem w ocamlu. Oczywiscie w kontekscietego, ze raz na tydzien z powodu jakiejs klasy musze w 1000 miejscach poprawaic kod. Czyli nie wychodze przez tydzien z pracy do domu, bo Xiński napisał klasę, a ja weekend mam zamknąc wersją ktora się kompiluje. > się czy inni grupowicze, odczuwali potrzebę takiej > konstrukcji w C++. Wszelakie automaty bardzo automatyczne są do bani. A propozycja nie kompilowania sie kodu, bo Xiński coś dodał i wszystko trzeba rzucać, w kąt, bo w 1000 miejscach kod się nie kompiluje, bo switch rzuca błędy, to ja dziękuję. > Ewentualnie ktoś coś może słyszał, że > były takie propozycje w przyszłej wersji standardu. Oby nie. > wychodzi na to, że swich + enum, ewentualnie wzorzec wizytor > wszystkim wystarcza :) Nie wystarcza, tylko nie stwarza mnóstwa problemów, ktore póki co widzę w Twoim wymaganiu. Wole to napisac zapomoca listy typow i iterowac ponich, wtedy, tylko tam gdzie prosze sie o guza dostane po glowie a nie wszedzie. Założenie jeden. Klasa która jest nieużywana, ale istnieje w kodzie powinna być poprawna syntaktycznie, ale nie powinna wywalać kompilacji. To jest IMHO karygodne. Pozdrawiam, Seweryn Habdank-Wojewódzki. |
|
|
|
|
| Podobne wątki | |
| Ciekawostka przyrodnicza Dziś zostałam uraczona chłodnikiem "litewskim" z... krewetkami, w zastępstwie raków, chyba. Hmmm... :/ |
|
| ciekawostka przyrodnicza > NH4(+) = NH3(+) + H ze niby wodor atomowy powstaje?? dziwne... |
|
| ciekawostka przyrodnicza Jestem dumnym posiadaczem dosyć wiekowego ale do tej pory spisującego się bez zarzutów kompa. Mój zestaw to Plyta główna Acorp 6bx67 z chipsetem 440BX Procesor Celeron 333,... |
|
| Ciekawostka przyrodnicza Co wam to przypomina? (reklama z Gadu-gadu - 17 KB) [..] |
|
|
Czasy w strefie GMT. Teraz jest 10:33. | Privacy Policy
|