Exception-Handler für Lambdas
-
Spendier ein zusätzliches Paar geschweifter Klammern:
int main() { auto lamb = [] { try {} catch(...){} }; }
-
seldon schrieb:
Spendier ein zusätzliches Paar geschweifter Klammern:
int main() { auto lamb = [] { try {} catch(...){} }; }Das ist eigentlich nicht was ich meinte. Hier wird ja einfach ein Block ins Lambda Compound-Statement gepackt. Ich meinte, ob das obige eigentlich syntaktisch legal ist.
Da hat mir trollfeeder schon ein weniger weiter geholfen.
-
trollfeeder schrieb:
Wie kommst du drauf, dass das legal sein könnte?
Ist mir auch ein Rätsel. Was soll überhaupt die Semantik davon sein?
-
Ich glaub, er meint sowas (Name ist mir entfallen)
void foo() try { ... } catch(...) { ... }in Lambda-Form. Nein, gibt es nicht.
-
Kellerautomat schrieb:
(Name ist mir entfallen)
Der übliche Name ist wohl "function level try block".
-
krümelkacker schrieb:
trollfeeder schrieb:
Wie kommst du drauf, dass das legal sein könnte?
Ist mir auch ein Rätsel. Was soll überhaupt die Semantik davon sein?
Ist das nicht etwas offensichtlich?
-
nn schrieb:
Kellerautomat schrieb:
(Name ist mir entfallen)
Der übliche Name ist wohl "function level try block".
Nein. Der Name laut Standard ist (function) try block.
-
Sone schrieb:
Ist das nicht etwas offensichtlich?
Nein, ich dachte der function try block verhält sich nur bei Exceptions in der Initialisierungsliste eines Konstruktors anders, als ein normaler try Block in einer Funktion.
Gibt es bei Lambdas ähnliche Situationen, die so ein Konstrukt erfordern würden ?
-
Edit: war kläglicher Unsinn.
-
Sone schrieb:
Ein function try block und ein try block unterscheiden sich durch nichts.
Lediglich dadurch, dass ein function try block ein try block ist, der direkt nach einer Funktionsdeklaration kommt:Ist der function try block nicht (noch vor dem 98er Standard ) eingeführt worden, um diesen Fall zu erschlagen ?
Foo::Foo() try : Bar(42) { } catch(...) { // Hier kann eine Exception aus Bar gefangen werden }Ich meine mich zu erinnern, das die ersten Compiler mit Exceptions den damals noch nicht kannten. Ist schon eine Weile her, gcc 2.x und Borland C++ 4.5.x
-
nn schrieb:
Sone schrieb:
Ein function try block und ein try block unterscheiden sich durch nichts.
Lediglich dadurch, dass ein function try block ein try block ist, der direkt nach einer Funktionsdeklaration kommt:Ist der function try block nicht (noch vor dem 98er Standard ) eingeführt worden, um diesen Fall zu erschlagen ?
Foo::Foo() try : Bar(42) { } catch(...) { // Hier kann eine Exception aus Bar gefangen werden }Ich meine mich zu erinnern, das die ersten Compiler mit Exceptions den damals noch nicht kannten. Ist schon eine Weile her, gcc 2.x und Borland C++ 4.5.x
Richtig, Funktion-try-Blöcke erlauben es, mit Exceptions, die aus Basisklassen oder Member während der Konstruktion oder der Zerstörung entweichen, umzugehen.
Bei allen anderen Funktionen gibt es nichts, was durch Function-try-Blöcke ermöglicht würde, was nicht auch mit normalen try_blöcken erledigt werden kann.
Ein handler eines Funktion-try-Blockes kann nicht durch return verlassen werden, und wenn der die Ausführung das Ende des Handlers eines solchen Function-try-Blockes erreicht, wird die Exception erneut geworfen. Zudem sind Alle Member und Basisklassen bei Erreichen des Handlers bereits zerstört. Das macht dieses Konstrukt nur mäßig nützlich, und da Destruktoren und Exceptionwerfen nicht gut zusammen passen, findet man sie nur gelegentlich in Konstruktoren.
-
Ist das nicht so, weil man beim Fortführen des Programms dann uninitialisierte Member hätte?
-
Ich zitiere mal hieraus:
http://www.drdobbs.com/sutters-mill-constructor-failures-or-the/184401316
Moral #1: Constructor function try block handlers are good only for translating an exception thrown from a base or member subobject constructor (and maybe to do related logging or some other side effects in response to such failures). They are not useful for any other purpose.
Moral #2: Destructor function try blocks have little or no practical use, because destructors should never emit an exception [7]. Thus there should never be anything for a destructor function try block to detect that couldn't be detected with a normal try block — and even if there were something to detect because of evil code (i.e., a member subobject whose destructor could throw), the handler would not be very useful for doing anything about it because it couldn't suppress the exception. The best it could do is would be to log something, or otherwise complain.
Moral #3: All other function try blocks have no practical use. A regular function try block can't catch anything that a regular try block within the function couldn't catch just as well.
Ich glaube das wurde eingeführt, weil C++ Entwickler dunkle Ecken in ihren Code fürchten, über die sie im Notfall keine Kontrolle hätten.

-
Sone schrieb:
Ist das nicht so, weil man beim Fortführen des Programms dann uninitialisierte Member hätte?
Nach dem Verständnis der Objektlebenszeit hätte man die Member dann garnicht - weil ja nie Konstruktoren dafür aufgerufen worden wären. Von einer Klasse X, die nicht trivial konstruierbar ist, gibt es keine uninitalisierten Objekte. Entweder das Objekt wurde korrekt initalisiert, oder es ist einfach nie dagewesen - der Compiler kann dann höchstens Speicher dafür allokiert haben.
Dass im catch eines function try blocks im/um den Ctor die member nicht vorhanden sind ist auch logisch: Wenn du Member A und B hast, weißt du (bzw. der Compiler) im try-Block nicht, ob die Exception aus A::A(), B::B() oder dem Funktionsrumpf gekommen ist, daher kann man nicht sicher sagen, welche Member überhaupt existieren/initialisiert wurden. Man kann auch argumentieren, dass bei einer Exception im Ctor das zu konstruierende Objekt nie komplett initialisiert wurde, daher nicht existiert, und ohne Objekt existieren auch keine Member.
-
pumuckl schrieb:
Nach dem Verständnis der Objektlebenszeit hätte man die Member dann garnicht - weil ja nie Konstruktoren dafür aufgerufen worden wären.
Das verstehe ich ja unter Initialisierung.
Andererseits hast du wieder mit dem Argument weiter unten Recht, dass ein Objekt nicht wirklich "da" ist, bzw. instanziiert ist, wenn nur der Speicher dafür vorhanden ist.Dass im catch eines function try blocks im/um den Ctor die member nicht vorhanden sind ist auch logisch: Wenn du Member A und B hast, weißt du (bzw. der Compiler) im try-Block nicht, ob die Exception aus A::A(), B::B() oder dem Funktionsrumpf gekommen ist, daher kann man nicht sicher sagen, welche Member überhaupt existieren/initialisiert wurden. Man kann auch argumentieren, dass bei einer Exception im Ctor das zu konstruierende Objekt nie komplett initialisiert wurde, daher nicht existiert, und ohne Objekt existieren auch keine Member.
Jo, THX
