noexcept, wieso nicht auch ohne Funktion?
-
Hiho,
ich hab' mich gefragt, wieso es eigentlich keine noexcept-Blöcke gibt? Unbenamste und unbedingte Scopes (also einfach nur {}-Paare) sind ja schon jetzt erlaubt, dann würde man diese einfach nur noch als noexcept kennzeichnen. So in etwa würde ich mir das vorstellen:
void foo() { Widget* w = new Widget; noexcept { int a = 5; a = w->bar(&a); } delete w; }Ich stelle mir das so vor, dass obiger Code garantiert sicher ist (i.e. keine Memoryleaks erzeugt). Wenn Widget::bar werfen könnte (also nicht noexcept ist), dann würde mir das der Compiler zur Compilezeit mitteilen und ich kann mir das genauer anschauen.
Diese Art von statischer Sicherheit ist es ja, was C++ so großartig macht.Grüßle
PS: bevor hier die gewöhnliche Armee an Korinthenkackern auftaucht: mir ist sehr wohl bewusst, dass new/delete nicht idiomatisch sind und std::unique_ptr mein konkretes Beispiel löst.
-
mir ist sehr wohl bewusst, dass new/delete nicht idiomatisch sind und std::unique_ptr mein konkretes Beispiel löst.
Aber was ist dann überhaupt der Anlass für dieses Feature? Debugging? Reicht IMO nicht für eine Sprachänderung. Schreib doch einfach
struct Call { template <typename X> Call(X&& x) {std::forward<X>(x)();} }; #define NOEXCEPT (Call) [&] () noexcept NOEXCEPT { // ... };Oder implementiere ein Attribut, dass
noexceptimpliziert, und schreib einfach[[nothrow]] { }Momentan ignoriert GCC Statement-Attribute. Müsste man alles anpassen, aber prinzipiell möglich.
-
eimalzin schrieb:
Wenn Widget::bar werfen könnte (also nicht noexcept ist), dann würde mir das der Compiler zur Compilezeit mitteilen und ich kann mir das genauer anschauen.
Das ist soweit ich weiss halt leider genau nicht so.
noexceptheisst nur dass das Programm abgebrochen wird falls doch ne Exception fliegt.http://en.cppreference.com/w/cpp/language/noexcept_spec
If a search for a matching exception handler leaves a function marked noexcept or noexcept(true), std::terminate is called immediately.
(...)
Note that a noexcept specification on a function is not a compile-time check; it is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions.
-
noexcept { int a = 5; a = w->bar(&a); }Ich stelle mir das so vor, dass obiger Code garantiert sicher ist (i.e. keine Memoryleaks erzeugt). Wenn Widget::bar werfen könnte (also nicht noexcept ist), dann würde mir das der Compiler zur Compilezeit mitteilen und ich kann mir das genauer anschauen.
man müsste es wohl eher so verstehen: falls eine exception geworfen wird, terminiere das programm so schnell wie möglich (=verzichte eventuell auf stack-unwinding), was du vielleicht doch nicht willst.
hustbaer schrieb:
eimalzin schrieb:
Wenn Widget::bar werfen könnte (also nicht noexcept ist), dann würde mir das der Compiler zur Compilezeit mitteilen und ich kann mir das genauer anschauen.
Das ist soweit ich weiss halt leider genau nicht so.
kann, muss aber nicht. und das ist "by-design", damit (u.a.) so etwas erlaubt ist:
double sqrt (double a) { if (a < 0) throw invalid_argument{}; return unsafe_sqrt(a); } double completely_safe (double a) noexcept { return sqrt(abs(a)); }Note that a noexcept specification on a function is not a compile-time check; it is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions.
es ist schon ein bisschen mehr - es ist nämlich eine ziemlich gute optimier-möglichkeit, aber nicht für compiler (bzw. nur marginal), sondern für libraries wie die standardbibliothek, die nämlich mithilfe std::move_if_noexcept und passend als noexcept deklarierte move-konstruktoren (zumeist implizit) die starke exception-safety garantie weiterhin behalten können (indem sie bei einem nicht-noexcept move-konstruktor auf den copy-ctor zurückgreifen).
noexcept sollte jedenfalls als teil des funktionsinterfaces verstanden werden (auch bei der entscheidung, ob man
noexcepthinschreibt oder nicht), und das wird in C++17 auch so formalisiert (P0012R1: Make exception specifications be part of the type system).jedenfalls sind das alles gründe, warum
noexceptfür einen block einfach "unpassend" ist (keine "wirkliche" noexceptions-garantie; fehlendes stack-unwinding; kein implementationsdetail, sondern teil des interfaces; eigentlich hauptsächlich/ursprünglich als last-minute lösung für die starke ausnahmegarantie in std::vector "erfunden" - jedenfalls hat man sich damals explizit gegen die block-lösung entschieden; und hier ein kommentar von bjarne stroustrup zu der frage To which extent can noexcept be deduced? und hier ein netter beitrag eines artikels von damals, der die basis für scott meyers effective modern c++/item 14 (declare functions noexcept if they won't emit exceptions) darstellt.
-
Also eigentlich müsste man Axioms einführen.
template <typename T> axiom bool NonNegative(T t /*auxiliary variable*/) { t > 0; // Expression constraint: must satisfy this for all NonNegative t. For debug purposes. UnsignedArithmetic -> T; /* Initialization rule: If the object is initialized by a type that satisfies the UnsignedArithmetic concept, it satisfies the NonNegative axiom */ } NonNegative double abs(double); double sqrt(double x) noexcept requires NonNegative(x);noexcept requiressagt aus, dasssqrt's Rumpf nicht werfen wird, falls der Compiler mittels ein paar simpler Regeln zeigen kann, dass das Argument NonNegative ist. Eine Regel haben wir implizit eingeführt: Funktionen und Klassen können NonNegative angegeben werden, und eine explizite Regel besagt, dass vorzeichenlose arithmetische Typen (die wir mittels einesconcepts definiert haben) als Initializer einNonNegativeergeben.Falls wir nun
double d = sqrt(abs(...));schreiben, wird diese Regeln angewandt, und die Menge der potenziellen Exceptions ist leer.
Wenn diese Regeln ausgeklügelt genug wären, könnten wir tatsächlich
noexcept"forcieren", und etwas korrektere Programme schreiben (natürlich kann der Progger immer noch dämlich sein und ein Axiom für einen Wert angeben, der diesem Axiom nicht gerecht wird).
-
Arcoth schrieb:
Also eigentlich müsste man Axioms einführen.
wenn ich mich recht erinnere, war das doch im allerursprünglichsen proposal zu concepts von annodazumal auch so drin (2006? 2007?) - bloß sind dann ja concepts aus -damals noch C++0x- wieder entfernt worden, dann die "lightweight"-concepts eingeführt worden, die es aber jetzt auch nichtmal nach C++17 schaffen. und statt axioms mit concepts gibt's jetzt dann wohl irgendwas mit preconditions/postconditions in attribut-art, was dem axiom-gedanken aber wieder nicht wirklich nahe kommt. leider hab ich auf die schnelle jetzt nichts besonders aussagekräfitges zum ursprünglichen concept-mit-axiom proposal gefunden (bzw. warum das dann rausgefallen ist). nur so etwas wie
And that’s it for today. There is much more to be told about axioms. Like, what is wrong with them, what technical issues they cause, how they should be used and how they can be overused. What they cannot do. But I will leave it for the next posts, if this one rises sufficient interest.
https://akrzemi1.wordpress.com/2012/01/11/concept-axioms-what-for/
wenn ich mich recht erinnere, verschwand das proposal / die axioms aber wegen widerstand der compilerbauer.