type erasure und std::exception_ptr
-
hustbaer schrieb:
Ich hab doch schon geschrieben "gute Idee, an die Möglichkeit hab' ich nicht gedacht"

Das hast du editiert.

Guck mal auf die Zeitstempel. Nein, ich wollte tatsächlich nur wissen, ob da nicht noch Fallen versteckt sind die du erkennen könntest.Tja, man kann Wrapper noch partiell Spezialisieren, sodass es dann auch für Skalare klappt, wie du schon erwähnt hast. Finale Klassen wären für diese Idee tatsächlich so nicht realisierbar.
Und die Sache dass man keine rohen Zeiger so damit verpacken kann, dass man sie als Zeiger auf ne Basisklasse wieder rausholen kann.
Hmm, eigentlich ein Einwand... das müsste doch machbar sein...
Das einzige was mir auf die Schnelle auffällt ist dass du einen dynamic_cast hinter einem static_cast versteckst, was ich nicht so gut finde. Aber wie gesagt, das ist Formsache, und darum geht's ja nicht.
Der User muss sich im Klaren sein, dass für den Konvertierungsoperator ein paar Takte draufgehen.
-
Sone schrieb:
hustbaer schrieb:
Ich hab doch schon geschrieben "gute Idee, an die Möglichkeit hab' ich nicht gedacht"

Das hast du editiert.

Guck mal auf die Zeitstempel. Nein, ich wollte tatsächlich nur wissen, ob da nicht noch Fallen versteckt sind die du erkennen könntest.Ja, hab editiert. Die Zeit dazwischen war aber so kurz dass ich nicht damit gerechnet habe dass es jmd. dazwischen gelesen hat.
EDIT: Wenn das Forum nicht spinnt, hab ich das doch nicht editiert. Denn der letzte EDIT betraf nur die
returnSache, den Absatz hab ich später nochmal editiert. Und es steht da ja "1x editiert". Oder zählt das Forum EDITs nicht wenn man sie super kurz nach dem posten macht? /EDITSone schrieb:
Und die Sache dass man keine rohen Zeiger so damit verpacken kann, dass man sie als Zeiger auf ne Basisklasse wieder rausholen kann.
Hmm, eigentlich ein Einwand... das müsste doch machbar sein...
Ich wüsste nicht wie. Falls es doch geht, immer her damit.
Wenn es ginge, dann wäre damit nämlich auch dir Wrapper-Klasse unnötig.Sone schrieb:
Das einzige was mir auf die Schnelle auffällt ist dass du einen dynamic_cast hinter einem static_cast versteckst, was ich nicht so gut finde. Aber wie gesagt, das ist Formsache, und darum geht's ja nicht.
Der User muss sich im Klaren sein, dass für den Konvertierungsoperator ein paar Takte draufgehen.
Ja, pfuh. Ich würde es halt eher über ne Member-Funktion machen. Oder über ne freie Funktion ala
dynamic_pointer_cast.
-
Wenn man beim Wrapper Komposition anstatt Vererbung verwendet, geht das auch für finale Klassen.
Und anstatt einem Crosscast von WrapperBase zu T, macht man halt einen downcast zu Wrapper und greift dort auf T zu.
-
@Nathan
Das geht nicht, weil mit KompositionWrapper<foo>nicht mitWrapper<printable>verwandt ist (und auch nicht mitfoooderprintable).Mit Vererbung ist
Wrapper<foo>aber mitfooverwandt, und dadurch auch mitprintable. Und dadurch kann man casten. Und daWrapperBasene virtuelle Funktion hat, kann man auchdynamic_castverwenden. Das ist ja der Trick der die ganze Sache überhaupt möglich macht.
-
Stimmt, der springende Punkt war ja, Vererbungsstrukturen beizubehalten.
Mein Fehler.
-
Hier die Version mit Skalaren, ich hoffe ich habe nicht zu viel Boilerplate produziert: http://ideone.com/4E9YZS
Mache mich jetzt an die Zeiger-Geschichte.
-
Die Erweiterung auf Skalare ist trivial, das hätte ich dir schon geglaubt dass du das hinbekommst.

Interessant - aber vermutlich unmöglich - ist die Geschichte mit den Zeigern.
-
hustbaer schrieb:
Die Erweiterung auf Skalare ist trivial, das hätte ich dir schon geglaubt dass du das hinbekommst.

Ich dachte, vielleicht will das ja tatsächlich mal jemand benutzen

vermutlich unmöglich
Es ist nicht unmöglich. Denn die Idee ist logisch. Solange die Idee richtig ist, kann und muss es auch richtigen Code geben. Irgendwo da draußen ist ein sauberer, völlig standardkonformer und hübscher Code, der nur darauf wartet von mir in der IDE eingetippt zu werden.
Das hier ist eine unportable und hässliche Variante. Sie ist Implementationsspezifisch und funktioniert wahrscheinlich nicht, laut Standard ist da ebenfalls nichts garantiert (wahrscheinlich UB, könnte man aber sicher auch ohne UB hinbekommen): http://ideone.com/SShuV3
Schon auf Ideone funktioniert die Variante mit den Skalaren nicht mehr. Obwohl Ideone sogar denselben Compiler verwendet wie ich. Und bei mir klappt es. Daher: Finger weg...
Das funktioniert nur deswegen, weil die Memberfunktionbefore()bei einigen Compilern die Vererbung berücksichtigt.
-
Der Code den du da aktuell hast kann nichtmal ansatzweise funktionieren.
Denk an Mehrfachvererbung und virtuelle Vererbung.
Und natürlich braucht man auch definiertes Verhalten für den Fall dass der Zeiger nicht konvertierbar ist.
-
Was ich dazu weiss: http://www.cplusplus.com/forum/articles/18756/
Die Möglichkeit relativ unkompliziert über Basisklassen auf Objekte in Type-Erasure-Containern
Das ist wiederspruechlich: An den Typ/Basistyp von Objekten zu gelangen, deren Typ geloescht ist. Warum sollte ich dann im Vorfeld type erasure anwenden? Auch ist mir unklar, welches Problem geloest werden soll. Nein, "öfters mal nützlich sein" hatte ich noch nie, wobei das kein wirkliches Kriterium ist
Type-Erasure-Containern
Was das sind, weiss ich nicht. Container mit type erased objecten? Dann spielen nur type erased objecte 'ne Rolle und der Container ist unwichtig.
Und warum bei Sone neuerdings alles
friendsein muss , ist mir auch unklar.
-
knivil schrieb:
Und warum bei Sone neuerdings alles
friendsein muss , ist mir auch unklar.Wenn du den Code nicht verstehst, dann verschwende ich nicht meine Zeit damit in dir zu erklären. Soviel sei gesagt: Die Factory braucht Zugriff auf den privaten Konstruktor. Diesen public zu machen, um deinen Ansprüchen genüge zu tun, würde dem User erlauben any_ptr irgendwie zu konstruieren... völliger Blödsinn.
-
Wenn du den Code nicht verstehst, dann verschwende ich nicht meine Zeit damit in dir zu erklären.
Und du laber mich nicht dumm von der Seite an, auch die friends in deinem Iteratorbeispiel konnten problemlos entfernt weden. Hoehenfluege?
-
knivil schrieb:
Wenn du den Code nicht verstehst, dann verschwende ich nicht meine Zeit damit in dir zu erklären.
Und du laber mich nicht dumm von der Seite an, auch die friends in deinem Iteratorbeispiel konnten problemlos entfernt weden. Hoehenfluege?
Gut, gut, gut. Tut mir Leid. Erkläre mir bitte, wie man das
friendentfernen kann, ohne die Syntax beim Aufruf zu verändern oder die Konstruktorenpubliczu machen oder sonst irgendwas.
Ich sehe keinen Weg. Und
friendist nur ein Schlüsselwort. Solange der User eine Funktionmake_any_ptraufrufen kann, undany_ptrprivateKonstruktoren hat, ist doch alles im Lot.
-
Kurze Erklaerung: Es gibt gewisse Schluesselreize, die Gefahr bedeuten, beispielsweise ist "new". Gleiches gilt fuer "friend". Selbst brauche ich es sehr wenig. Bis jetzt 2 Mal insgesamt. Waehrend fuer "new" direkte Loesungsmoeglichkeiten bestehen, ist "friend" eher ein konzeptionelles Problem. Und bevor ich das angehe, wuerde ich gern wissen, warum man gerne den Typ eines type erased objects haben moechte, bzw. warum man dann in erster Linie ueberhaupt type erasure nutzt. Bei boost::variant erhaelt man das mit 'nem Visitor, ist wohl aber nicht das gesuchte.
-
@knivil
Ein Type Erasure Container ist sowas wieboost::any.Und die Forderung an den Typ zu kommen ist überhaupt nicht widersprüchlich - das macht man bei Type-Erasure im Prinzip immer. Nur dass es meist hinter spezialisierten privaten Hilfs-Klassentemplates versteckt wird.
Beispiel für wo so etwas nützlich sein könnte wäre eine Registry für Objekte beliebigen Typs. Denk an Dependency Injection Frameworks o.ä. Bzw. auch einfach als Erweiterung von boost::any o.ä.
Was ich nicht verstehe, ist warum bei Fragen wie diesen oft so patzige Antworten kommen. OK, du hast keine Verwendung dafür. Fein. Noted. Kann man aber auch freundlicher sagen.
Das selbe gilt für
friend.friendist ein recht nützlicher Bestandteil von C++, der dabei hilft die Kapselung zu verstärken. Natürlich kann man auch so arbeiten als ob esfriendnicht gäbe. Dann wird manfriendauch nicht brauchen. Oh Wunder. Was aber nicht heisst dass man dabei unbedingt den besten Code produziert.
-
Was ich nicht verstehe, ist warum bei Fragen wie diesen oft so patzige Antworten kommen.
Zeig sie mir bitte in meinem Eingangspost. Ansonsten: Fuer geegeben Aktion habe ich mich fuer gegeben Reaktion entschieden. An anderen Tagen haette ich mich anders entschieden.
OK, du hast keine Verwendung dafür. Fein. Noted. Kann man aber auch freundlicher sagen.
Habe ich dazugeschrieben, dass das kein Kriterium. Kann man freundlich sagen, habe mich aber fuer netral entschieden. Es ist definitive nicht unfreundlich. Und zu friend habe ich mich bereits geaessert.
Ein Type Erasure Container ist sowas wie boost::any
Ich dachte boost::any ist einfach nur ein besseres void*.
Und die Forderung an den Typ zu kommen ist überhaupt nicht widersprüchlich - das macht man bei Type-Erasure im Prinzip immer.
Und meine Erfahrung widerspricht dem, deswegen habe ich ja von meiner Erfahrung berichtet. Ich verwende Type erasure im klassischen Sinn.
-
knivil schrieb:
Was ich nicht verstehe, ist warum bei Fragen wie diesen oft so patzige Antworten kommen.
Zeig sie mir bitte in meinem Eingangspost. Ansonsten: Fuer geegeben Aktion habe ich mich fuer gegeben Reaktion entschieden. An anderen Tagen haette ich mich anders entschieden.
OK, du hast keine Verwendung dafür. Fein. Noted. Kann man aber auch freundlicher sagen.
Habe ich dazugeschrieben, dass das kein Kriterium. Kann man freundlich sagen, habe mich aber fuer netral entschieden. Es ist definitive nicht unfreundlich.
Hab deinen (an mich gerichteten) Beitrag nochmal gelesen. Du hast Recht. Sorry. Deine Korrespondenz mit Sone hat da beim ersten mal Lesen auf meine Erinnerung an deinen ersten Beitrag hier abgefärbt.
knivil schrieb:
Ein Type Erasure Container ist sowas wie boost::any
Ich dachte boost::any ist einfach nur ein besseres void*.
Ja, pfuh. Ich weiss nicht ob Type Erasure Container ein viel verwendeter Ausdruck ist. Aber irgendwie muss man es ja nennen. Ich nenne es halt Type Erasure Container. Wie würdest du es nennen (ausser "besseres void*")?
knivil schrieb:
Und die Forderung an den Typ zu kommen ist überhaupt nicht widersprüchlich - das macht man bei Type-Erasure im Prinzip immer.
Und meine Erfahrung widerspricht dem, deswegen habe ich ja von meiner Erfahrung berichtet. Ich verwende Type erasure im klassischen Sinn.
Also ich hätte mir schon hin und wieder mal die Möglichkeit gewünscht aus nem
any"Interface-Zeiger" bekommen zu können.
Oder noch besser: gleich nendynamic_castausgehend vonvoid*machen zu können.
Mir ist klar dass das nicht dem "C++ way of doing things" entspricht. Nur manchmal passt der "C++ way of doing things" nicht so gut, und der "C# way of doing things" wäre viel angenehmer für einen bestimmten Programmteil. Da nervt dann der quasi nicht-vorhandene Reflection-Support von C++ etwas.Ich bei solchen Dingen kein Tagebuch, und da ich auch kein idetisches Gedächtnis habe, und ich mir solche Dinge zugegebenermassen nicht jeden Tag wünsche, kann ich auch kein konkretes Beispiel liefern.