boost:::variant<> fuer C++/CLI .NET? (oder sowas in der Art)



  • Sorry dass ich den "uralten" Artikel ausgrab, mir ist grad eingefallen, dass das vor kurzem mal Thema war..

    Jochen Kalmbach schrieb:

    Helium schrieb:

    Jochen Kalmbach schrieb:

    und was Dir bei "Object^" fehlt...

    Typsicherheit?

    ?????
    .NET ist die Typsicherste Sprache die es gibt!!!

    Die viele Punktuation macht diese Lüge auch nicht zutreffender.

    1. .NET ist keine Sprache
    2. Haskell ist wesentlich typsicherer als C# oder C++/CLI

    Jochen Kalmbach schrieb:

    Was fehlt Dir bei "is" oder "as"???
    Bau Dir halt ein "Wrapper" um "Object" was Dir alle von Dir benötigten Type unterstützt....

    Kann das "int" und "char" und "std::type_info const *"? (Autoboxing ist eine Entschuldigung, keine Antwort.)



  • Mr. N schrieb:

    1. .NET ist keine Sprache

    Ja. Im eifer des gefechts bringt man das leicht durcheinander...

    Mr. N schrieb:

    Jochen Kalmbach schrieb:

    Was fehlt Dir bei "is" oder "as"???
    Bau Dir halt ein "Wrapper" um "Object" was Dir alle von Dir benötigten Type unterstützt....

    Kann das "int" und "char" und "std::type_info const *"? (Autoboxing ist eine Entschuldigung, keine Antwort.)

    Verstehe ich jetzt nicht ganz...



  • Jochen Kalmbach schrieb:

    Mr. N schrieb:

    1. .NET ist keine Sprache

    Ja. Im eifer des gefechts bringt man das leicht durcheinander...

    Gefecht? 😃

    Jochen Kalmbach schrieb:

    Mr. N schrieb:

    Jochen Kalmbach schrieb:

    Was fehlt Dir bei "is" oder "as"???
    Bau Dir halt ein "Wrapper" um "Object" was Dir alle von Dir benötigten Type unterstützt....

    Kann das "int" und "char" und "std::type_info const *"? (Autoboxing ist eine Entschuldigung, keine Antwort.)

    Verstehe ich jetzt nicht ganz...

    Kann man in Object^ den Wert von &typeid(X) speichern? Schließlich sind typeid-Werte wohl kaum Managed und haben keine Kopierkonstruktor, daher muss man den Pointer nehmen. Oder soll ich mir dafür schon wieder ne Wrapper-Klasse bauen? Das ist aber wesentlich unbequemer, als einfach boost::variant<> zu nehmen...



  • Ich verstehe gerade den Zweck von dem & vor dem typeid nicht so ganz... Was spricht gegen "System::Type"?



  • Jochen Kalmbach schrieb:

    Ich verstehe gerade den Zweck von dem & vor dem typeid nicht so ganz... Was spricht gegen "System::Type"?

    Da C++/CLI unter Linux nicht geht, kenn ich das Zeug nicht. Ich bin naiverweise davon ausgegangen, dass es eine Variante von C++ ist, in der es daher legitim ist, die Standardbibliothek und Standardkeywords wie typeid zu benutzen. Offensichtlich nicht, da wie mir scheint alle Standarddinge nochmal implementiert wurden und man die Microsoft-Varianten benutzen muss. Was der Sinn von C++/CLI ist entzieht sich dann allerdings meinem Verständnis. Muss man sich ja immer erst überlegen, ob man ein Sprachfeature benutzen darf oder nicht... 🙄



  • Mr. N schrieb:

    Jochen Kalmbach schrieb:

    Ich verstehe gerade den Zweck von dem & vor dem typeid nicht so ganz... Was spricht gegen "System::Type"?

    Da C++/CLI unter Linux nicht geht, kenn ich das Zeug nicht. Ich bin naiverweise davon ausgegangen, dass es eine Variante von C++ ist

    Ich würde eher sagen, eine Erweiterung...
    Wie soll man denn in ein "freies" C++-System ein 100% sicheres Typsystem integrieren, ohne dass man neue Ding erfindet?
    typeid gibt es natürlich wieterhin noch und Du kannst das auch in ein "Object^" reinstecken... Es wird dann eben der Type reingesteckt...



  • Jochen Kalmbach schrieb:

    Mr. N schrieb:

    Jochen Kalmbach schrieb:

    Ich verstehe gerade den Zweck von dem & vor dem typeid nicht so ganz... Was spricht gegen "System::Type"?

    Da C++/CLI unter Linux nicht geht, kenn ich das Zeug nicht. Ich bin naiverweise davon ausgegangen, dass es eine Variante von C++ ist

    Ich würde eher sagen, eine Erweiterung...
    Wie soll man denn in ein "freies" C++-System ein 100% sicheres Typsystem integrieren, ohne dass man neue Ding erfindet?
    typeid gibt es natürlich wieterhin noch und Du kannst das auch in ein "Object^" reinstecken... Es wird dann eben der Type reingesteckt...

    Es klang so als ging dies nicht.

    Was ist ein "100% sicheres Typsystem"?

    Wieso soll man eigentlich keinen Managed- und Unmanaged-Code vermischen?

    Naja ich benutze wohl weiterhin mein gutes altes C++, auch weil C++/CLI bei mir nicht geht. 🙂



  • Mr. N schrieb:

    Was ist ein "100% sicheres Typsystem"?

    Das wirklich *alles* von einer Basisklasse abgeleitet ist und Du somit auch *alles* in ein "Object^" reinstopfen kannst (=> Variant).

    Mr. N schrieb:

    Wieso soll man eigentlich keinen Managed- und Unmanaged-Code vermischen?

    Die Sprache ist eigentlich dazu da, dass man die beiden mischt. Man sollte es nur nicht machen, wenn man weder von "C/C++" noch von "C++/CLI" Ahnung hat 😉 dann bringt man immer mehr durcheinander, als dass man wirklich was nützliches dabei machen kann...



  • Jochen Kalmbach schrieb:

    Mr. N schrieb:

    Was ist ein "100% sicheres Typsystem"?

    Das wirklich *alles* von einer Basisklasse abgeleitet ist und Du somit auch *alles* in ein "Object^" reinstopfen kannst (=> Variant).

    Unter "sicher" versteh ich eher das Gegenteil. Dass man eben so wenig "stopfen" kann wie möglich. Und da ist z.B. Haskell wesentlich besser.

    Und... ist "int" wirklich von Object abgeleitet??

    Jochen Kalmbach schrieb:

    Mr. N schrieb:

    Wieso soll man eigentlich keinen Managed- und Unmanaged-Code vermischen?

    Die Sprache ist eigentlich dazu da, dass man die beiden mischt. Man sollte es nur nicht machen, wenn man weder von "C/C++" noch von "C++/CLI" Ahnung hat 😉 dann bringt man immer mehr durcheinander, als dass man wirklich was nützliches dabei machen kann...

    Das hab ich dann wohl nicht richtig verstanden. Es gibt übrigens kein "C/C++".



  • Jochen Kalmbach schrieb:

    Mr. N schrieb:

    Was ist ein "100% sicheres Typsystem"?

    Das wirklich *alles* von einer Basisklasse abgeleitet ist und Du somit auch *alles* in ein "Object^" reinstopfen kannst (=> Variant).

    Geht mit ganz normalem C++ auch. Siehe boost::any. boost::variant sieht zwar ganz ähnlich aus wird aber ganz anders benutzt.



  • Ben04 schrieb:

    Geht mit ganz normalem C++ auch. Siehe boost::any.

    Aber nichts *zwangsweise*. Sondern nur wenn jeder Programmierer sich auch daran hält...

    Mr. N schrieb:

    Und... ist "int" wirklich von Object abgeleitet??

    Ja.

    Mr. N schrieb:

    Unter "sicher" versteh ich eher das Gegenteil.

    Du kannst ja zu *jeder Zeit* nachprüfen/fragen, was für einen Type Du gerade hast.



  • Jochen Kalmbach schrieb:

    Mr. N schrieb:

    Unter "sicher" versteh ich eher das Gegenteil.

    Du kannst ja zu *jeder Zeit* nachprüfen/fragen, was für einen Type Du gerade hast.

    Explizit? Allein die Tatsache, dass es Object gibt verleitet doch dazu, das nicht zu machen...



  • Jochen Kalmbach schrieb:

    Ben04 schrieb:

    Geht mit ganz normalem C++ auch. Siehe boost::any.

    Aber nichts *zwangsweise*. Sondern nur wenn jeder Programmierer sich auch daran hält...

    boost::any geht mit jedem Typen, der einen Kopierkonstruktor hat.



  • Der *größte* Unterschied zu normalem C++ ist die Typsicherheit, was auch bedeutet: Du kannst zwar in Deinem Source-Code casten wie Du willst. Zur Laufzeit wird aber *sichergestellt* das der cast auch geht! Sonst wird eine Exception geworfen!

    Also ein

    ref class A{};
    ref class B{};
    

    kannst Du zwar beides in ein "Object" reintun, aber das zurückcasten geht eben nur, wenn es zur Laufzeit auch als "ok" akzeptiert ist:

    Object^ a = gcnew A();
    Object^ b = gcnew B();
    A ^aa = (A^) b;
    B ^bb = (B^) a;
    

    Lässt sich wunderbar compilieren, wird zur Laufzeit aber eine Exception werfen.

    In normalem C++ dagegen wirft dies auch zur Laufzeit keine Exception, sondern Dein Code macht halt irgendwas damit und solche Dinge führen meistens zu abstürzen und sind auch schwer zu finden (natürlich nicht in diesem trivialen Beispiel)...



  • Jochen Kalmbach schrieb:

    Der *größte* Unterschied zu normalem C++ ist die Typsicherheit, was auch bedeutet: Du kannst zwar in Deinem Source-Code casten wie Du willst. Zur Laufzeit wird aber *sichergestellt* das der cast auch geht! Sonst wird eine Exception geworfen!

    Also ein

    ref class A{};
    ref class B{};
    

    kannst Du zwar beides in ein "Object" reintun, aber das zurückcasten geht eben nur, wenn es zur Laufzeit auch als "ok" akzeptiert ist:

    Object^ a = gcnew A();
    Object^ b = gcnew B();
    A ^aa = (A^) b;
    B ^bb = (B^) a;
    

    Lässt sich wunderbar compilieren, wird zur Laufzeit aber eine Exception werfen.

    In normalem C++ dagegen wirft dies auch zur Laufzeit keine Exception, sondern Dein Code macht halt irgendwas damit und solche Dinge führen meistens zu abstürzen und sind auch schwer zu finden (natürlich nicht in diesem trivialen Beispiel)...

    Klingt irgendwie nach dynamic_cast. Das wirft nämlich auch ne Exception...

    Natürlich braucht man dazu eine gemeinsame Basisklasse, aber das ist doch nur gut.

    Grundsätzlich bevorzuge ich es, Fehler zur Compilezeit vor die Nase geworfen zu bekommen. Da gibt es dann wesentlich bessere Sprachen als C++ und C++/CLI, aber irgendwie bleib ich immer bei C++ hängen. 😃



  • Jochen Kalmbach schrieb:

    Der *größte* Unterschied zu normalem C++ ist die Typsicherheit, was auch bedeutet: Du kannst zwar in Deinem Source-Code casten wie Du willst. Zur Laufzeit wird aber *sichergestellt* das der cast auch geht! Sonst wird eine Exception geworfen!

    Hättest du dir die Dokumentation von boost::any angeschaut (etwa 4 lesbar formatierte Seiten inklusive Reference) wüsstest du, dass dies auch mit boost::any möglich ist. Wird ein Zeiger auf any gecastetet so wird der richtige Wert oder NULL zurückgegeben. Bei Referencen wird im Fehlerfall boost::bad_any_cast geworfen. Einen ungeprüften downcast eines boost::any ist nur durch hacken möglich.

    boost::variant bietet zwar ähnliche Methoden an jedoch wird hier empfohlen immer mit Visitoren zu arbeiten anstatt eines Downcasts. (Das ist auch wesentlich sicherer!)

    Jochen Kalmbach schrieb:

    Der *größte* Unterschied zu normalem C++ ist die Typsicherheit, was auch bedeutet: Du kannst zwar in Deinem Source-Code casten wie Du willst. Zur Laufzeit wird aber *sichergestellt* das der cast auch geht! Sonst wird eine Exception geworfen!

    Dies ist keine Erfindung von C++/CIL sondern ist schon seit schon über gut einem Jahrzehnt bei jedem C++ Compiler unter dem Namen dynamic_cast dabei.

    Sowieso finde ich, dass du ein komisches Verständnis von Sicherheit hast.

    • Beim einem native Programm kommt es zu einer Zugriffsverletzung in Folge eines falschen ungeschützten Casts, das Betriebssystem greift ein und beendet das Programm. Bei den meisten Betriebssystemen kann das Programm Veto einlegen und den Fehler behandeln, bei Windows durch ein Ausnahmesystem. Wie dies geht ist irrelevant da man eh Programmierungsfehler nicht zur Laufzeit behandeln kann.
    • Beim einem .net Programm kommt es zu einer einer Exception wegen eines falschen Casts. Das Programm fängt sie nicht ab das es sich nicht selbst patchen kann. Danach beendet die .NET Runtime das Programm aufgrund einer ungefangen Ausnahme.

    Das Resultat ist also genau das gleiche, egal ob .NET oder native. Gleiches Resultat ist in meinen Augen gleiche Sicherheit.



  • Wäre es nicht geil, wenn man sich das ganze rumcasten sparen könnte und das per Pattern Matching erledigen könnte?



  • Beim einem .net Programm kommt es zu einer einer Exception wegen eines falschen Casts. Das Programm fängt sie nicht ab das es sich nicht selbst patchen kann. Danach beendet die .NET Runtime das Programm aufgrund einer ungefangen Ausnahme.

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-171928.html



  • [edit] total am Thema vorbei [/edit]



  • Ben04 schrieb:

    Hättest du dir die Dokumentation von boost::any angeschaut (etwa 4 lesbar formatierte Seiten inklusive Reference) wüsstest du, dass dies auch mit boost::any möglich ist.

    Hab ich doch nie abgestritten... Aber: Du kannst dann trotzdem noch wild casten wie Du willst ohne dass es jemand prüft! boost::any ist nix in der Sprache oder dem Compiler eingebautes Feature! Das ist der entscheidende Unterschied...


Anmelden zum Antworten