Brug af std::apply on std::expected in C++23

C++

Strømlining af fejlhåndtering i C++23

Effektiv håndtering af fejl og styring af afkastværdier er afgørende i dagens C++-udvikling. Den typiske metode til at arbejde med funktioner, der returnerer {std::expected} typer inkluderer en masse kontroller og fejlhåndteringskode, som kan komplicere logikken og gøre koden sværere at vedligeholde.

Denne artikel undersøger brugen af ​​en mere sofistikeret og generel metode til at forenkle fejlhåndtering. For at reducere boilerplate-koden og forbedre læsbarheden, vil vi undersøge konstrueringen af ​​en `magic_apply`-metode, der samler resultaterne af mange {std::expected}-værdier og sender dem til en anden funktion.

Kommando Beskrivelse
std::expected En skabelontype brugt i C++ til fejlhåndtering, der har mulighed for at gemme både værdier og fejl.
std::unexpected Når det bruges sammen med std::expected, repræsenterer det en uventet fejlværdi.
template<typename...> Skitserer en variadisk skabelon med en uendelig mængde skabelonargumenter, som den kan acceptere.
decltype Anvendes i skabelonprogrammering, især for at finde ud af typen af ​​udtryk.
args.value() Hvis et std::expected objekt har en værdi, får adgang til den værdi, der er indeholdt i det.
args.has_value() Bekræfter, om en værdi er til stede i et std::expected objekt.
(... && args.has_value()) For at bestemme, om hvert std::expected objekt har værdier, skal du folde udtrykket.
func(args.value()...) Bruger værdierne af std::expected-objekterne til at kalde metoden func.
return unexpected<Err>(args.error()...) Returnerer en uventet fejl, der indeholder fejlene fra std::expected-objekterne.

Effektiv fejlhåndtering ved hjælp af variable skabeloner

De type bruges i scripts for at lette fejlhåndtering i C++23. Hovedmålet er at udvikle en generisk funktion kaldet der kan overføre output fra flere værdier til en anden funktion. Ved at gøre dette, den kedelige fejlkontrol, der normalt er nødvendig, når man arbejder med mange std::expected værdier reduceres. er ret fleksibel, fordi den kan tage et vilkårligt antal parametre ved at bruge variadiske skabeloner. Inden du kalder funktionen med indholdet af evt objekt, den grundlæggende logik af magic_apply anvender et foldudtryk, , for at sikre alle objekter har gyldige værdier.

Denne idé er illustreret i det første script-eksempel ved hjælp af simple typer som f.eks og . Den definerer en funktion, der udfører en grundlæggende beregning, og getA og funktioner, der vender tilbage typer. Hvis begge værdierne fra og getB er legitime, kan vi ringe bruger ; hvis ikke, spredes fejlen. Ved at reducere boilerplate-koden forbedrer denne metode læsbarheden og vedligeholdelsesvenligheden. En lignende idé præsenteres i det andet script, men for at fremhæve tilgangens alsidighed, typer og lambda functions bruges.

Reducerer kompleksiteten i C++ fejlhåndtering med `std::expected}

C++23-script ved hjælp af Variadic-skabeloner

#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;
}

Kombination af forskellige {std::expected} resultater C++23 værdier

C++23-script ved hjælp af lambda-funktioner

#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;
}

Forbedring af C++-fejlhåndtering med Variadic-skabeloner

Kapaciteten af at forbedre fejlhåndteringen i indviklede systemer i høj grad er en anden afgørende fordel ved at anvende det i C++. At kombinere resultaterne af mange asynkrone handlinger problemfrit er afgørende i situationer, hvor de giver efter typer. Ud over at gøre koden enklere, garanterer denne metode en stærk fejlhåndtering. Mere alsidige og generiske funktioner kan skabes ved at kombinere et vilkårligt antal værdier med variadic templates.

Alsidigheden af gør det muligt at bruge det sammen med funktioner, der har en række forskellige argumenttyper. Implementeringen gøres yderligere enklere ved at bruge , som automatisk udleder returtypen for det kombinerede funktionskald. Desuden kan denne teknik udvides til at håndtere mere indviklede opgaver, herunder sammenlægning værdier med andre fejltyper eller ændring af værdierne, før de sendes til funktionen. På grund af dets tilpasningsevne kan mønsteret bruges til en bred vifte af opgaver, fra ligetil beregninger til komplekse operationer.

Ofte stillede spørgsmål om Variadic-skabeloner og std::expected

  1. Hvad er ?
  2. Det er en C++ skabelontype, der kan indeholde en fejl eller en gyldig værdi og bruges til fejlhåndtering.
  3. Hvordan gør arbejde?
  4. Det eliminerer behovet for gentagne fejltjek ved at kombinere resultaterne af talrige værdier og overføre dem til en funktion.
  5. Hvad er variadiske skabeloner?
  6. Variable skabeloner giver en stor grad af frihed i funktionsdesign ved at gøre det muligt for funktioner at acceptere et vilkårligt antal parametre.
  7. Hvorfor bruge i ?
  8. Udnyttelse af værdierne af objekter for automatisk at bestemme returtypen for den funktion, der kaldes.
  9. Er i stand til at håndtere forskellige fejltyper?
  10. Ja, den kan laves til at fungere med værdier med forskellige fejltyper med nogle få justeringer.
  11. Hvilke fordele udnytter tilbud?
  12. Når du håndterer fejl, giver det en mere udtryksfuld og renere tilgang end med mere konventionelle teknikker som undtagelser eller returkoder.
  13. Er del af ?
  14. Ud over , repræsenterer i virkeligheden en forkert værdi.
  15. Kan asynkrone handlinger udnyttes med ?
  16. Det er faktisk tilpasningsdygtigt at håndtere værdier returneret af asynkrone operationer.
  17. Hvad er et foldudtryk?
  18. Her bruges funktionen i C++ kaldet fold udtryk til at tjekke om alle objekter indeholder gyldige værdier på en enkel måde.

I C++23 forbedrer implementering af en generisk funktion til at håndtere flere std::expected-værdier kodens læsbarhed i høj grad og forenkler fejlhåndteringen. Magic_apply-funktionen reducerer boilerplate-koden og forbedrer vedligeholdelsesevnen ved at bruge variadic-skabeloner for at sikre, at alle forventede værdier er korrekte før behandling. Denne metode tilbyder en fleksibel løsning, der kan anvendes i forskellige situationer og giver moderne C++ programmering en renere og mere effektiv måde at håndtere fejl på.