Verwendung von std::apply für std::expected in C++23

C++

Optimierte Fehlerbehandlung in C++23

Der effektive Umgang mit Fehlern und die Verwaltung von Rückgabewerten sind in der heutigen C++-Entwicklung von entscheidender Bedeutung. Die typische Methode zum Arbeiten mit Funktionen, die {std::expected}-Typen zurückgeben, umfasst viele Prüfungen und Fehlerbehandlungscode, was die Logik komplizieren und die Wartung des Codes erschweren kann.

In diesem Artikel wird die Verwendung einer ausgefeilteren und allgemeineren Methode zur Vereinfachung des Fehlermanagements untersucht. Um den Boilerplate-Code zu reduzieren und die Lesbarkeit zu verbessern, untersuchen wir die Konstruktion einer „magic_apply“-Methode, die die Ergebnisse vieler {std::expected}-Werte aggregiert und an eine andere Funktion übergibt.

Befehl Beschreibung
std::expected Ein in C++ zur Fehlerbehandlung verwendeter Vorlagentyp, der sowohl Werte als auch Fehler speichern kann.
std::unexpected Stellt bei Verwendung mit std::expected einen unerwarteten Fehlerwert dar.
template<typename...> Skizziert eine variadische Vorlage mit einer unendlichen Anzahl von Vorlagenargumenten, die sie akzeptieren kann.
decltype Wird bei der Vorlagenprogrammierung verwendet, insbesondere um die Art des Ausdrucks herauszufinden.
args.value() Wenn ein std::expected-Objekt einen Wert hat, greift es auf den darin enthaltenen Wert zu.
args.has_value() Überprüft, ob ein Wert in einem std::expected-Objekt vorhanden ist.
(... && args.has_value()) Um zu bestimmen, ob jedes std::expected-Objekt Werte hat, falten Sie den Ausdruck.
func(args.value()...) Verwendet die Werte der std::expected-Objekte, um die Methode func aufzurufen.
return unexpected<Err>(args.error()...) Gibt einen unerwarteten Fehler zurück, der die Fehler der std::expected-Objekte enthält.

Effektives Fehlermanagement durch variable Vorlagen

Der Der Typ wird in den Skripten verwendet, um die Fehlerbehandlung in C++23 zu vereinfachen. Das Hauptziel besteht darin, eine generische Funktion namens zu entwickeln das die Ausgabe mehrerer übertragen kann Werte in eine andere Funktion umwandeln. Dadurch entfällt die mühsame Fehlerprüfung, die normalerweise bei der Arbeit mit vielen Fehlern erforderlich ist std::expected Werte werden reduziert. ist recht flexibel, da beliebig viele davon benötigt werden können Parameter mithilfe verschiedener Vorlagen. Vor dem Aufruf der Funktion mit dem Inhalt von any Objekt, die grundlegende Logik von magic_apply verwendet einen Faltausdruck, , um sicherzustellen, dass alle Objekte haben gültige Werte.

Diese Idee wird im ersten Skriptbeispiel anhand einfacher Typen wie veranschaulicht Und . Es definiert a Funktion, die eine grundlegende Berechnung durchführt, und getA Und Funktionen, die zurückkehren Typen. Wenn beide Werte aus Und getB legitim sind, können wir anrufen verwenden ; Wenn nicht, wird der Fehler weitergegeben. Durch die Reduzierung des Boilerplate-Codes verbessert diese Methode die Lesbarkeit und Wartbarkeit. Eine ähnliche Idee wird im zweiten Skript vorgestellt, aber um die Vielseitigkeit des Ansatzes hervorzuheben, Typen und lambda functions werden verwendet.

Reduzieren der Komplexität bei der C++-Fehlerbehandlung mit „std::expected}“

C++23-Skript mit Variadic-Vorlagen

#include <expected>
#include <string>
#include <iostream>
#include <tuple>

using namespace std;

template<typename Func, typename... Args, typename Err>
auto magic_apply(Func func, const expected<Args, Err>&... args) -> expected<decltype(func(args.value()...)), Err> {
    if ((... && args.has_value())) {
        return func(args.value()...);
    } else {
        return unexpected<Err>(args.error()...);
    }
}

expected<int, string> getA(int x) {
    if (x > 0) return x;
    return unexpected<string>("Error in getA");
}

expected<double, string> getB(double y) {
    if (y > 0) return y;
    return unexpected<string>("Error in getB");
}

double compute_all(int a, double b) {
    return a + b;
}

int main() {
    auto result = magic_apply(compute_all, getA(10), getB(20.5));
    if (result) {
        cout << "Result: " << result.value() << endl;
    } else {
        cout << "Error: " << result.error() << endl;
    }
    return 0;
}

Kombinieren verschiedener {std::expected}-Ergebnisse C++23-Werte

C++23-Skript mit Lambda-Funktionen

#include <expected>
#include <string>
#include <iostream>

using namespace std;

template<typename Func, typename... Args, typename Err>
auto magic_apply(Func func, const expected<Args, Err>&... args) -> expected<decltype(func(args.value()...)), Err> {
    bool all_valid = (args.has_value() && ...);
    if (all_valid) {
        return func(args.value()...);
    } else {
        return unexpected<Err>(args.error()...);
    }
}

expected<string, string> getA(bool flag) {
    if (flag) return "SuccessA";
    return unexpected<string>("Failed A");
}

expected<string, string> getB(bool flag) {
    if (flag) return "SuccessB";
    return unexpected<string>("Failed B");
}

string compute_all(const string& a, const string& b) {
    return a + " and " + b;
}

int main() {
    auto result = magic_apply(compute_all, getA(true), getB(true));
    if (result) {
        cout << "Result: " << result.value() << endl;
    } else {
        cout << "Error: " << result.error() << endl;
    }
    return 0;
}

Verbessern der C++-Fehlerbehandlung mit Variadic-Vorlagen

Die Kapazität von Die deutlich verbesserte Fehlerbehandlung in komplizierten Systemen ist ein weiterer entscheidender Vorteil der Verwendung in C++. Die nahtlose Kombination der Ergebnisse vieler asynchroner Aktionen ist in Situationen, in denen sie nachgeben, von entscheidender Bedeutung Typen. Diese Methode vereinfacht nicht nur den Code, sondern garantiert auch eine starke Fehlerbehandlung. Durch die Kombination beliebig vieler Funktionen können vielseitigere und allgemeinere Funktionen erstellt werden Werte mit variadic templates.

Die Vielseitigkeit von ermöglicht die Verwendung mit Funktionen, die eine Vielzahl von Argumentarten akzeptieren. Die Implementierung wird durch die Verwendung weiter vereinfacht , wodurch automatisch der Rückgabetyp des kombinierten Funktionsaufrufs abgeleitet wird. Darüber hinaus kann diese Technik erweitert werden, um komplexere Aufgaben, einschließlich Zusammenführungen, zu bewältigen Werte mit anderen Fehlerarten oder Ändern der Werte vor dem Senden an die Funktion. Aufgrund seiner Anpassungsfähigkeit kann das Muster für eine Vielzahl von Aufgaben verwendet werden, von einfachen Berechnungen bis hin zu komplexen Operationen.

Häufig gestellte Fragen zu Variadic-Vorlagen und std::expected

  1. Was ist ?
  2. Es handelt sich um einen C++-Vorlagentyp, der einen Fehler oder einen gültigen Wert enthalten kann und zur Fehlerverwaltung verwendet wird.
  3. Wie funktioniert arbeiten?
  4. Durch die Kombination der Ergebnisse mehrerer Fehler entfällt die Notwendigkeit wiederholter Fehlerprüfungen Werte und deren Übergabe an eine Funktion.
  5. Was sind Variadic-Vorlagen?
  6. Variable Vorlagen bieten viel Freiheit beim Funktionsdesign, indem sie es Funktionen ermöglichen, eine beliebige Anzahl von Parametern zu akzeptieren.
  7. Warum verwenden? In ?
  8. Nutzung der Werte der Objekte, um den Rückgabetyp der aufgerufenen Funktion automatisch zu bestimmen.
  9. Ist in der Lage, verschiedene Fehlertypen zu behandeln?
  10. Ja, es kann so gestaltet werden, dass es funktioniert Werte mit verschiedenen Fehlerarten mit ein paar Optimierungen.
  11. Welche Vorteile bietet die Nutzung Angebot?
  12. Beim Umgang mit Fehlern bietet es einen aussagekräftigeren und saubereren Ansatz als konventionellere Techniken wie Ausnahmen oder Rückkehrcodes.
  13. Ist Teil von ?
  14. Zusätzlich zu , stellt tatsächlich einen falschen Wert dar.
  15. Können asynchrone Aktionen verwendet werden? ?
  16. Es ist in der Tat anpassungsfähig in der Handhabung Werte, die von asynchronen Vorgängen zurückgegeben werden.
  17. Was ist ein Faltausdruck?
  18. Hier wird die Funktion „Fold Expression“ in C++ verwendet, um zu überprüfen, ob alle vorhanden sind Objekte enthalten auf einfache Weise gültige Werte.

In C++23 verbessert die Implementierung einer generischen Funktion zur Verarbeitung mehrerer std::expected-Werte die Lesbarkeit des Codes erheblich und vereinfacht die Fehlerbehandlung erheblich. Die magic_apply-Funktion reduziert den Boilerplate-Code und verbessert die Wartbarkeit, indem sie verschiedene Vorlagen verwendet, um sicherzustellen, dass alle erwarteten Werte vor der Verarbeitung korrekt sind. Diese Methode bietet eine flexible Lösung, die auf verschiedene Situationen angewendet werden kann und der modernen C++-Programmierung eine sauberere und effektivere Möglichkeit zur Fehlerbehandlung bietet.