Naudojant std::apply std::tikimasi C++23

Naudojant std::apply std::tikimasi C++23
Naudojant std::apply std::tikimasi C++23

Klaidų tvarkymo supaprastinimas C++23

Veiksmingas klaidų valdymas ir grąžinimo verčių valdymas yra labai svarbūs šiandienos C++ kūrimui. Įprastas būdas dirbti su funkcijomis, kurios grąžina {std::expected} tipus, apima daugybę patikrinimų ir klaidų apdorojimo kodo, todėl gali būti sudėtinga logika ir kodą būtų sunkiau prižiūrėti.

Šiame darbe nagrinėjamas sudėtingesnis ir bendresnis metodas klaidų valdymui supaprastinti. Siekdami sumažinti pagrindinį kodą ir pagerinti skaitomumą, ištirsime, kaip sukurti „magic_apply“ metodą, kuris sujungia daugelio {std::expected} reikšmių rezultatus ir perduoda jas kitai funkcijai.

komandą Aprašymas
std::expected Šablono tipas, naudojamas C++ klaidoms tvarkyti, turintis galimybę saugoti ir reikšmes, ir klaidas.
std::unexpected Kai naudojamas su std::expected, reiškia netikėtą klaidos reikšmę.
template<typename...> Nubrėžia įvairų šabloną su begaliniu skaičiumi šablono argumentų, kuriuos jis gali priimti.
decltype Naudojamas šablonų programavimui, ypač norint išsiaiškinti išraiškos tipą.
args.value() Jei std::expected objektas turi reikšmę, pasiekia joje esančią reikšmę.
args.has_value() Patikrina, ar std::expected objekte yra reikšmė.
(... && args.has_value()) Norėdami nustatyti, ar kiekvienas std::expected objektas turi reikšmes, sulenkite išraišką.
func(args.value()...) Naudoja std::expected objektų reikšmes, kad iškviestų metodą func.
return unexpected<Err>(args.error()...) Pateikia netikėtą klaidą, kurioje yra klaidų iš std::expected objektų.

Veiksmingas klaidų valdymas naudojant kintamuosius šablonus

The std::expected tipas naudojamas scenarijuose, kad būtų lengviau valdyti klaidas C++23. Pagrindinis tikslas yra sukurti bendrąją funkciją, vadinamą magic_apply kuri gali perduoti kelių išvestį std::expected reikšmes į kitą funkciją. Tai darant varginantis klaidų tikrinimas, kuris paprastai reikalingas dirbant su daugeliu std::expected vertės sumažinamos. magic_apply yra gana lankstus, nes gali prireikti bet kokio skaičiaus std::expected parametrus naudojant variadic šablonus. Prieš iškviesdami funkciją su bet kurio turiniu std::expected objektas, pagrindinė logika magic_apply naudoja lenkimo išraišką, (... && args.has_value()), kad įsitikintumėte, jog viskas std::expected objektai turi galiojančias reikšmes.

Ši idėja iliustruota pirmame scenarijaus pavyzdyje naudojant paprastus tipus, tokius kaip int ir double. Ji apibrėžia a compute_all funkcija, kuri atlieka pagrindinį skaičiavimą, ir getA ir getB grįžtančios funkcijos std::expected tipai. Jei abi vertės iš getA ir getB yra teisėti, galime paskambinti compute_all naudojant magic_apply; jei ne, klaida plinta. Sumažinus pagrindinį kodą, šis metodas pagerina skaitymo ir priežiūros galimybes. Panaši idėja pateikta antrajame scenarijuje, tačiau norint pabrėžti šio požiūrio universalumą, string rūšys ir lambda functions yra naudojami.

C++ klaidų tvarkymo sudėtingumo mažinimas naudojant `std::expected}

C++23 scenarijus naudojant variadic šablonus

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

Sujungus skirtingas {std::expected}, gaunamos C++23 reikšmės

C++23 scenarijus naudojant Lambda funkcijas

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

C++ klaidų valdymo tobulinimas naudojant variadic šablonus

Pajėgumas std::expected labai pagerinti klaidų valdymą sudėtingose ​​sistemose yra dar vienas esminis privalumas, kai naudojamas C++. Daugelio asinchroninių veiksmų rezultatų sklandus derinimas yra labai svarbus situacijose, kai jie duoda rezultatų std::expected tipai. Šis metodas ne tik supaprastina kodą, bet ir garantuoja stiprų klaidų tvarkymą. Sujungus bet kokį skaičių funkcijų galima sukurti universalesnių ir bendresnių funkcijų std::expected vertybes su variadic templates.

Universalumas magic_apply leidžia jį naudoti su funkcijomis, kurios priima įvairius argumentų tipus. Įgyvendinimas dar labiau supaprastinamas naudojant decltype, kuris automatiškai nustato kombinuotos funkcijos skambučio grąžinimo tipą. Be to, šią techniką galima išplėsti, kad būtų galima valdyti sudėtingesnes užduotis, įskaitant sujungimą std::expected reikšmes su kitomis klaidų rūšimis arba pakeisti reikšmes prieš siunčiant jas į funkciją. Dėl savo pritaikomumo modelis gali būti naudojamas įvairioms užduotims, nuo paprastų skaičiavimų iki sudėtingų operacijų.

Dažnai užduodami klausimai apie Variadic šablonus ir std::expected

  1. Kas yra std::expected?
  2. Tai C++ šablono tipas, kuriame gali būti klaida arba tinkama reikšmė ir kuris naudojamas klaidų valdymui.
  3. Kaip veikia magic_apply dirbti?
  4. Tai pašalina poreikį pakartotinai tikrinti klaidas, nes sujungia daugelio rezultatų rezultatus std::expected reikšmes ir perduodant jas funkcijai.
  5. Kas yra kintamieji šablonai?
  6. Kintamieji šablonai suteikia daug laisvės kuriant funkcijas, nes leidžia funkcijoms priimti bet kokį parametrų skaičių.
  7. Kodėl naudoti decltype in magic_apply?
  8. Naudojant vertybes std::expected objektus, kad automatiškai nustatytų iškviečiamos funkcijos grąžinimo tipą.
  9. Is magic_apply gali valdyti įvairių tipų klaidas?
  10. Taip, jis gali veikti std::expected vertės, turinčios įvairių klaidų tipų su keliais pataisymais.
  11. Kokius privalumus suteikia panaudojimas std::expected pasiūlyti?
  12. Tvarkant klaidas, jis siūlo išraiškingesnį ir švaresnį požiūrį nei naudojant įprastesnius metodus, pvz., išimtis ar grąžinimo kodus.
  13. Is std::unexpected dalis std::expected?
  14. Be to std::expected, std::unexpected iš tikrųjų reiškia neteisingą vertę.
  15. Ar galima naudoti asinchroninius veiksmus magic_apply?
  16. Jis tikrai pritaikomas tvarkyti std::expected asinchroninėmis operacijomis grąžintos reikšmės.
  17. Kas yra lenkimo išraiška?
  18. Čia C++ funkcija, vadinama sulenkimo išraiška, naudojama norint patikrinti, ar viskas std::expected objektuose paprastai yra galiojančių reikšmių.

Užbaigimas:

C++23 kalboje įdiegus bendrąją funkciją, skirtą tvarkyti kelias std::expected reikšmes, labai pagerėja kodo skaitomumas ir labai supaprastinamas klaidų tvarkymas. Funkcija „magic_apply“ sumažina pagrindinį kodą ir pagerina priežiūrą, naudodama įvairius šablonus, kad įsitikintų, jog visos numatytos reikšmės yra teisingos prieš apdorojant. Šis metodas siūlo lankstų sprendimą, kurį galima pritaikyti įvairiose situacijose, o šiuolaikiniam C++ programavimui suteikia švaresnį ir efektyvesnį būdą tvarkyti gedimus.