Bruke std::apply on std::expected in C++23

C++

Effektivisering av feilhåndtering i C++23

Effektiv håndtering av feil og håndtering av avkastningsverdier er avgjørende i dagens C++-utvikling. Den typiske metoden for å jobbe med funksjoner som returnerer {std::expected}-typer inkluderer mange kontroller og feilhåndteringskode, som kan komplisere logikken og gjøre koden vanskeligere å vedlikeholde.

Denne artikkelen undersøker bruken av en mer sofistikert og generell metode for å forenkle feilhåndtering. For å redusere standardkode og forbedre lesbarheten, vil vi undersøke å konstruere en `magic_apply`-metode som samler resultatene av mange {std::expected} verdier og sender dem til en annen funksjon.

Kommando Beskrivelse
std::expected En maltype som brukes i C++ for feilhåndtering som har mulighet til å lagre både verdier og feil.
std::unexpected Når brukt med std::expected, representerer en uventet feilverdi.
template<typename...> Skisserer en variadisk mal med en uendelig mengde malargumenter som den kan akseptere.
decltype Brukes i malprogrammering, spesielt for å finne ut type uttrykk.
args.value() Hvis et std::expected-objekt har en verdi, får du tilgang til verdien i det.
args.has_value() Verifiserer om en verdi er tilstede i et std::expected objekt.
(... && args.has_value()) For å finne ut om hvert std::expected objekt har verdier, brett uttrykket.
func(args.value()...) Bruker verdiene til std::expected-objektene til å kalle metoden func.
return unexpected<Err>(args.error()...) Returnerer en uventet feil som inneholder feilene fra std::expected-objektene.

Effektiv feilhåndtering ved bruk av variable maler

De type brukes i skriptene for å lette feilhåndtering i C++23. Hovedmålet er å utvikle en generisk funksjon kalt som kan overføre utdata fra flere verdier til en annen funksjon. Ved å gjøre dette, den kjedelige feilkontrollen som vanligvis er nødvendig når man jobber med mange std::expected verdiene reduseres. er ganske fleksibel fordi det kan ta et hvilket som helst antall parametere ved å bruke variadiske maler. Før du kaller opp funksjonen med innholdet i evt objekt, den grunnleggende logikken til magic_apply bruker et fold-uttrykk, , for å sikre at alle objekter har gyldige verdier.

Denne ideen er illustrert i det første skripteksemplet ved å bruke enkle typer som f.eks og . Den definerer en funksjon som utfører en grunnleggende beregning, og getA og funksjoner som kommer tilbake typer. Hvis begge verdiene fra og getB er legitime, kan vi ringe bruker ; hvis ikke, spres feilen. Ved å redusere boilerplate-koden forbedrer denne metoden lesbarheten og vedlikeholdsevnen. En lignende idé presenteres i det andre manuset, men for å fremheve tilnærmingens allsidighet, typer og lambda functions brukes.

Reduserer kompleksiteten i C++ feilhåndtering med `std::expected}

C++23-skript som bruker variadiske maler

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

Kombinere forskjellige {std::expected} resultater C++23-verdier

C++23-skript som bruker lambda-funksjoner

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

Forbedre C++-feilhåndtering med Variadic-maler

Kapasiteten til Å forbedre feilhåndteringen i intrikate systemer er en annen viktig fordel ved å bruke det i C++. Å kombinere resultatene av mange asynkrone handlinger sømløst er avgjørende i situasjoner når de gir resultat typer. I tillegg til å gjøre koden enklere, garanterer denne metoden sterk feilhåndtering. Mer allsidige og generiske funksjoner kan opprettes ved å kombinere et vilkårlig antall verdier med variadic templates.

Allsidigheten til lar den brukes med funksjoner som tar inn en rekke argumenttyper. Implementeringen gjøres ytterligere enklere ved å utnytte , som automatisk trekker returtypen til det kombinerte funksjonskallet. Videre kan denne teknikken utvides til å håndtere mer intrikate oppgaver, inkludert sammenslåing verdier med andre feiltyper eller endre verdiene før de sendes til funksjonen. På grunn av tilpasningsevnen kan mønsteret brukes til et bredt spekter av oppgaver, fra enkle beregninger til komplekse operasjoner.

Ofte stilte spørsmål om Variadic-maler og std::expected

  1. Hva er ?
  2. Det er en C++-maltype som kan inneholde en feil eller en gyldig verdi og brukes til feilhåndtering.
  3. Hvordan gjør det arbeid?
  4. Det eliminerer behovet for gjentatte feilkontroller ved å kombinere resultatene fra mange verdier og overføre dem til en funksjon.
  5. Hva er variadiske maler?
  6. Variable maler gir en stor del frihet i funksjonsdesign ved å gjøre det mulig for funksjoner å akseptere et vilkårlig antall parametere.
  7. Hvorfor bruke i ?
  8. Bruke verdiene til objekter for automatisk å bestemme returtypen til funksjonen som kalles.
  9. Er i stand til å håndtere ulike feiltyper?
  10. Ja, den kan lages for å fungere med verdier som har forskjellige feiltyper med noen få justeringer.
  11. Hvilke fordeler har å utnytte tilby?
  12. Når du håndterer feil, tilbyr den en mer uttrykksfull og renere tilnærming enn med mer konvensjonelle teknikker som unntak eller returkoder.
  13. Er del av ?
  14. I tillegg til , representerer faktisk en feil verdi.
  15. Kan asynkrone handlinger utnyttes med ?
  16. Det er faktisk tilpasningsdyktig å håndtere verdier returnert av asynkrone operasjoner.
  17. Hva er et fold-uttrykk?
  18. Her brukes funksjonen i C++ kalt fold-uttrykk for å sjekke om alle objekter inneholder gyldige verdier på en enkel måte.

I C++23 vil implementering av en generisk funksjon for å håndtere flere std::expected verdier forbedre kodens lesbarhet og i stor grad forenkle feilhåndtering. Magic_apply-funksjonen reduserer boilerplate-koden og forbedrer vedlikeholdsevnen ved å bruke variadiske maler for å sikre at alle forventede verdier er korrekte før behandling. Denne metoden tilbyr en fleksibel løsning som kan brukes i forskjellige situasjoner og gir moderne C++-programmering en renere og mer effektiv måte å håndtere feil på.