Library: capture and transport the exception itself
...using the std::exception_ptr and helpers, we can now reliably transport any exception object as the »right« value of the »Either«
This commit is contained in:
parent
4348e110cb
commit
9c0fa7139d
4 changed files with 210 additions and 44 deletions
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
|
||||
/** @file result.hpp
|
||||
** Intermediary value object to represent the result of an operation.
|
||||
** This operation might have produced a value result or failed with an exception.
|
||||
** Typically, the Result token is used _inline_ -- immediately either invoking
|
||||
** Intermediary value object to represent »either« an operation result or a failure.
|
||||
** Some operation might have produced a value result or failed with an exception.
|
||||
** Typically, the Result token is used _inline_ — immediately either invoking
|
||||
** one of the member function or employing the built-in result type conversion.
|
||||
** It will be copyable iff the result value is copyable. There is an implicit
|
||||
** valid or failure state, which can be tested. Any attempt to get the value
|
||||
|
|
@ -42,15 +42,14 @@
|
|||
#include "lib/wrapper.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
||||
using util::isnil;
|
||||
using std::string;
|
||||
namespace error = lumiera::error;
|
||||
|
||||
|
||||
|
|
@ -74,27 +73,27 @@ namespace lib {
|
|||
template<>
|
||||
class Result<void>
|
||||
{
|
||||
string failureLog_;
|
||||
std::exception_ptr failure_;
|
||||
|
||||
public:
|
||||
/** mark either failure (default) or success */
|
||||
Result (bool success =false)
|
||||
: failureLog_{success? "": "operation failed"}
|
||||
: failure_{success? nullptr: std::make_exception_ptr (error::State{"operation failed"})}
|
||||
{ }
|
||||
|
||||
/** failed result, with reason given.*/
|
||||
Result (lumiera::Error const& reason)
|
||||
: failureLog_{reason.what()}
|
||||
: failure_{std::make_exception_ptr (reason)}
|
||||
{ }
|
||||
|
||||
operator bool() const { return isValid(); }
|
||||
bool isValid() const { return isnil (failureLog_); }
|
||||
bool isValid() const { return not failure_; }
|
||||
|
||||
void
|
||||
maybeThrow() const
|
||||
{
|
||||
if (not isValid())
|
||||
throw error::State (failureLog_);
|
||||
if (failure_)
|
||||
std::rethrow_exception(failure_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -115,12 +114,7 @@ namespace lib {
|
|||
wrapper::ItemWrapper<RES> value_;
|
||||
|
||||
public:
|
||||
/** mark an invalid/failed result */
|
||||
Result (string const& failureReason ="no result")
|
||||
: Result<void>{failureReason}
|
||||
{ }
|
||||
|
||||
/** failed result, with reason given.*/
|
||||
/** mark failed result, with reason given.*/
|
||||
Result (lumiera::Error const& reason)
|
||||
: Result<void>{reason}
|
||||
{ }
|
||||
|
|
@ -131,6 +125,7 @@ namespace lib {
|
|||
, value_{std::forward<RES> (value)}
|
||||
{ }
|
||||
|
||||
// is or is not copyable depending on RES
|
||||
|
||||
|
||||
operator RES() const
|
||||
|
|
@ -158,9 +153,9 @@ namespace lib {
|
|||
}
|
||||
};
|
||||
|
||||
/** deduction guard: allow _perfect forwarding_ of a any result into the ctor call. */
|
||||
template<typename VAL>
|
||||
Result (VAL&& x) -> Result<VAL>;
|
||||
|
||||
Result (VAL&&) -> Result<VAL>;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ namespace model {
|
|||
struct ElementAccess::TypeConverter
|
||||
: RawResult::Visitor
|
||||
{
|
||||
lib::Result<TAR&> result{"not convertible to desired target widget"};
|
||||
lib::Result<TAR&> result{error::Invalid{"not convertible to desired target widget"}};
|
||||
|
||||
template<typename X> // note the "backward" use. We pick that base interface
|
||||
using canUpcast = std::is_convertible<TAR*, X>; // into which our desired result type can be upcast, because
|
||||
|
|
@ -150,7 +150,7 @@ namespace model {
|
|||
result = *downcasted;
|
||||
}
|
||||
else
|
||||
result = lib::Result<TAR&>{"access returns empty answer"};
|
||||
result = lib::Result<TAR&>{error::State{"access returns empty answer"}};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ namespace test{
|
|||
|
||||
namespace error = lumiera::error;
|
||||
using error::LUMIERA_ERROR_FATAL;
|
||||
using error::LUMIERA_ERROR_STATE; ///////////////////TODO
|
||||
|
||||
|
||||
namespace {
|
||||
|
|
@ -89,12 +88,12 @@ namespace test{
|
|||
CHECK (not isSameObject (sequel.get<Literal const&>(), THE_END));
|
||||
|
||||
// »Either Right« case : mark as failure
|
||||
Result<double> facepalm{error::Fatal()};
|
||||
Result<double> facepalm{error::Fatal("zOMG")};
|
||||
CHECK (not facepalm.isValid());
|
||||
|
||||
VERIFY_ERROR (STATE, (double)facepalm );
|
||||
VERIFY_ERROR (STATE, facepalm.get<double&>());
|
||||
VERIFY_ERROR (STATE, facepalm.maybeThrow() );
|
||||
VERIFY_ERROR (FATAL, (double)facepalm );
|
||||
VERIFY_ERROR (FATAL, facepalm.get<double&>());
|
||||
VERIFY_ERROR (FATAL, facepalm.maybeThrow() );
|
||||
|
||||
CHECK (42.0 == facepalm.getOrElse([]{ return 42; }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79584,14 +79584,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695749704247" ID="ID_827179831" MODIFIED="1695749714510" TEXT="Rückgabewert per lib::Result">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1695749704247" ID="ID_827179831" MODIFIED="1695776492378" TEXT="Rückgabewert per lib::Result">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1695749715525" ID="ID_914625209" MODIFIED="1695749847745" TEXT="das ist ein Either-Typ">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695749719789" ID="ID_1636786367" MODIFIED="1695749844541" TEXT="diesen modernisieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1695749730882" ID="ID_720335444" MODIFIED="1695749749631" TEXT="sollte einen std::exception_ptr nehmen">
|
||||
<node COLOR="#338800" CREATED="1695749719789" ID="ID_1636786367" MODIFIED="1695776447431" TEXT="diesen modernisieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1695749730882" ID="ID_720335444" MODIFIED="1695776449174" TEXT="sollte einen std::exception_ptr nehmen">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1695749758416" ID="ID_1018098640" MODIFIED="1695749764076" TEXT="dieser dient als Varianten-Flag"/>
|
||||
<node CREATED="1695749764647" ID="ID_160637410" MODIFIED="1695749781209">
|
||||
|
|
@ -79620,6 +79620,26 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1695779117581" ID="ID_313781081" MODIFIED="1695779285785">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
incl <i>perfect forwarding</i>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#7c86a6" DESTINATION="ID_1103669600" ENDARROW="Default" ENDINCLINATION="-1340;79;" ID="Arrow_ID_171962477" STARTARROW="None" STARTINCLINATION="-729;83;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1695779300895" ID="ID_877020791" MODIFIED="1695779311935" TEXT="Result_test">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695776467076" ID="ID_992547663" MODIFIED="1695776489819" TEXT="den »Either« value (lib::Result) per policy einbringen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -79634,7 +79654,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1695657111918" ID="ID_463997820" MODIFIED="1695657217094" TEXT="in Sub-Namespace lib::thread">
|
||||
<arrowlink COLOR="#6e85a1" DESTINATION="ID_750029588" ENDARROW="Default" ENDINCLINATION="-741;56;" ID="Arrow_ID_1885189676" STARTARROW="None" STARTINCLINATION="-489;0;"/>
|
||||
</node>
|
||||
<node CREATED="1695747369039" ID="ID_1807166092" MODIFIED="1695747532236" TEXT="immer noch unklar und problematisch">
|
||||
<node CREATED="1695747369039" ID="ID_1807166092" MODIFIED="1695770884835" TEXT="immer noch unklar und problematisch">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -79660,8 +79680,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
hab das gestern versucht — so kann das nicht stehen bleiben, das ist ja lächerlich (brauche explizite Template-Instantiierung) — zumindest solange wir keine C++-Module verwenden (C++20)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1695747673046" ID="ID_1466067755" MODIFIED="1695747692667">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -79673,8 +79692,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
die Code-Anordnung <i>hat keinen Flow</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
<node CREATED="1695747880669" ID="ID_1803056303" MODIFIED="1695748482205" TEXT="die erzwungene »Joinable«-Variante wirkt mutwillig">
|
||||
|
|
@ -79687,8 +79705,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Ich habe doch selber oben diese Prinzipien formuliert: eine Library-Lösung sollte nicht mutwillig beschränken, sondern eine sinnvolle Gliederung anbieten...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#fed5c5" DESTINATION="ID_1859841213" ENDARROW="Default" ENDINCLINATION="1276;51;" ID="Arrow_ID_1453893581" STARTARROW="None" STARTINCLINATION="1738;-79;"/>
|
||||
<arrowlink COLOR="#8c5869" DESTINATION="ID_1245905649" ENDARROW="Default" ENDINCLINATION="10;123;" ID="Arrow_ID_155554446" STARTARROW="None" STARTINCLINATION="129;7;"/>
|
||||
</node>
|
||||
|
|
@ -79703,8 +79720,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
also vielleicht doch <b>Policy-based-Design</b>?
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1695748635886" ID="ID_859201330" MODIFIED="1695748676734" TEXT="aaber ... dann wird ja alles noch umständlicher">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
|
|
@ -79722,8 +79738,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
⟹ wenn überhaupt, müßte die Policy einen <i>mittleren Binding-Layer </i>bilden
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1695749319298" ID="ID_1308996711" MODIFIED="1695749370296" TEXT="eine Policy für Fehlerbehandlung + Rückgabewert + Join wäre gerechtfertigt">
|
||||
<linktarget COLOR="#dd26d2" DESTINATION="ID_1308996711" ENDARROW="Default" ENDINCLINATION="194;-5;" ID="Arrow_ID_1982134212" SOURCE="ID_1477111545" STARTARROW="None" STARTINCLINATION="172;16;"/>
|
||||
|
|
@ -79748,8 +79763,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Policy <font size="5"><b>⤵</b></font> <font color="#07097c" face="Monospaced">main<POL,FUN,ARGS...></font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1695749669204" ID="ID_1950929730" MODIFIED="1695749680246" TEXT="Front-End: wie bisher"/>
|
||||
|
|
@ -89176,6 +89190,164 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1695776592132" ID="ID_1103669600" LINK="https://en.cppreference.com/w/cpp/language/class_template_argument_deduction#Deduction_for_class_templates" MODIFIED="1695779285785" TEXT="via Class Template Argument Deduction (CTAD)">
|
||||
<linktarget COLOR="#7c86a6" DESTINATION="ID_1103669600" ENDARROW="Default" ENDINCLINATION="-1340;79;" ID="Arrow_ID_171962477" SOURCE="ID_313781081" STARTARROW="None" STARTINCLINATION="-729;83;"/>
|
||||
<node CREATED="1695776635546" ID="ID_536392621" MODIFIED="1695776837788" TEXT="geht normalerweise nicht — da keine »universelle Referenz«">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Wenn man eine Klasse C<T> hat, und einen Konstruktur definiert, der ein T&& - Argument nimmt, dann ist das T bereits durch den Klassen-Templateparameter <i>festgelegt; </i>es kommt in diesem Fall nicht zu einem <i>reference collapsing, </i>sondern es handelt sich einfach um eine rvalue-Referenz T&&. Symptom "can not bind rvalue reference to lvalue"
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1695776839723" ID="ID_304077427" MODIFIED="1695776912034" TEXT="Ein Konstruktor mit separatem Template-Parameter kann nicht deduziert werden">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...denn in diesem Fall würde es sich zwar um eine »universelle Referenz« handeln, aber der Zusammenhang zum Klassen-Template-Parameter ist nicht klar
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1695776913649" ID="ID_247930242" MODIFIED="1695777249133" TEXT="Abhilfe: expliziten deduction guide schreiben">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li>
|
||||
steht im enclosing scope <i>nach</i> der Template-Definition
|
||||
</li>
|
||||
<li>
|
||||
syntaktisch eine frei stehende Funktions-Deklaration mit einem <i>trailing return type</i>, welcher die resultierende Template-Spezialisierung konstruieren muß (kann beliebig komplexe Typ-Ausdrücke enthalten)
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<u>Beispiel </u>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced">  /** deduction guard: allow _perfect forwarding_ of a any result into the ctor call. */ </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced">  template<typename VAL> </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced">  Result (VAL&&) -> Result<VAL>; </font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1695777446740" ID="ID_1737574962" MODIFIED="1695778365679" TEXT="mit ist nicht klar, warum das dann funktioniert gemäß Standard">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Wenn ich die Beschreibung in CPPReference.com richtig verstehe, dann würde ohne expliziten deduction guide folgender guide automatisch generiert:
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
template<class X>
|
||||
</p>
|
||||
<p>
|
||||
class C {
|
||||
</p>
|
||||
<p>
|
||||
  C(X&& val);
|
||||
</p>
|
||||
<p>
|
||||
};
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<u>Auto-Guides</u>:
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
template<class X>
|
||||
</p>
|
||||
<p>
|
||||
C<X> g1(X&& val)
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
template<class X>
|
||||
</p>
|
||||
<p>
|
||||
C<X> g2(C<X>)
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<u>Hilfs-Deduction+Resolution...</u>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
struct S {
|
||||
</p>
|
||||
<p>
|
||||
  template<class X>
|
||||
</p>
|
||||
<p>
|
||||
  S(X&&);
|
||||
</p>
|
||||
<p>
|
||||
  template<class X>
|
||||
</p>
|
||||
<p>
|
||||
  S(C<X>);
|
||||
</p>
|
||||
<p>
|
||||
};
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
S = <initializer>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<font color="#8b2626"><b>Was ich nicht verstehe</b></font>: der gemäß Regeln auto-generierte Guide sieht <i>exakt genauso aus, </i>wie der Guide, den man manuell definieren muß, damit es funktioniert. Warum wird dann hier ein anderer Typ deduziert? Ich habe Experimente gemacht: ohne den manuellen deduction Guide ergibt sich für einen <initializer> ≔ int&  ⟼ ein deduzierter Parameter X = int  (was dann natürlich scheitert)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1622386272743" ID="ID_1645901699" MODIFIED="1622386277362" TEXT="I/O">
|
||||
<node CREATED="1622386278646" ID="ID_359102162" MODIFIED="1622386285472" TEXT="sehr große Dateien">
|
||||
|
|
|
|||
Loading…
Reference in a new issue