Veakäsitluse sujuvamaks muutmine C++23-s
Vigade tõhus käsitlemine ja tagastusväärtuste haldamine on tänapäeva C++ arenduses hädavajalik. Tüüpiline töömeetod funktsioonidega, mis tagastavad tüüpi {std::expected}, sisaldab palju kontrolle ja veakäsitluse koodi, mis võib loogikat keerulisemaks muuta ja koodi hooldamist keerulisemaks muuta.
Selles artiklis uuritakse keerukama ja üldisema meetodi kasutamist vigade haldamise lihtsustamiseks. Katsekoodi vähendamiseks ja loetavuse parandamiseks uurime meetodi "magic_apply" loomist, mis koondab paljude {std::expected} väärtuste tulemused ja edastab need teisele funktsioonile.
Käsk | Kirjeldus |
---|---|
std::expected | Mallitüüp, mida kasutatakse C++-s vigade käsitlemiseks ja millel on võimalus salvestada nii väärtusi kui ka vigu. |
std::unexpected | Kui kasutatakse koos std::expected, tähistab ootamatu vea väärtus. |
template<typename...> | Joonistab varieeruva malli koos lõpmatu hulga malliargumentidega, mida see võib aktsepteerida. |
decltype | Kasutatakse mallide programmeerimisel, eriti avaldise tüübi väljaselgitamiseks. |
args.value() | Kui objektil std::expected on väärtus, pääseb see juurde selles sisalduvale väärtusele. |
args.has_value() | Kontrollib, kas std::expected objektis on väärtus. |
(... && args.has_value()) | Selleks et teha kindlaks, kas igal std::expected objektil on väärtused, voldi avaldis kokku. |
func(args.value()...) | Kasutab std::expected objektide väärtusi meetodi func kutsumiseks. |
return unexpected<Err>(args.error()...) | Tagastab ootamatu vea, mis sisaldab std::expected objektide vigu. |
Tõhus tõrkehaldus muutuvate mallide abil
The std::expected tüüpi kasutatakse skriptides, et hõlbustada C++23 vigade käsitlemist. Peamine eesmärk on välja töötada üldine funktsioon nimega magic_apply mis suudab edastada mitme väljundi std::expected väärtused teisele funktsioonile. Seda tehes tüütu veakontroll, mis on tavaliselt paljudega töötamisel vajalik std::expected väärtused vähenevad. magic_apply on üsna paindlik, sest selleks võib kuluda suvaline arv std::expected parameetrid, kasutades variadic malle. Enne funktsiooni kutsumist mis tahes sisuga std::expected objekt, põhiloogika magic_apply kasutab voltimisväljendit, (... && args.has_value()), et kõik oleks kindel std::expected objektidel on kehtivad väärtused.
Seda ideed illustreerib esimene skripti näide, kasutades lihtsaid tüüpe, näiteks int ja double. See määratleb a compute_all funktsioon, mis teostab põhiarvutuse ja getA ja getB funktsioonid, mis tagastavad std::expected tüübid. Kui mõlemad väärtused alates getA ja getB on õigustatud, võime helistada compute_all kasutades magic_apply; kui ei, siis viga levib. Vähendades standardkoodi, suurendab see meetod loetavust ja hooldatavust. Sarnane idee on esitatud teises stsenaariumis, kuid et rõhutada lähenemisviisi mitmekülgsust, string tüübid ja lambda functions kasutatakse.
C++ veakäsitluse keerukuse vähendamine käsuga `std::expected}
C++23 skript, kasutades variadic malle
#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;
}
Erinevate {std::expected} kombineerimine annab tulemuseks C++23 väärtused
Lambda funktsioone kasutav C++23 skript
#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++ veakäsitluse parandamine variadic mallidega
Võimsus std::expected vigade käsitlemise märkimisväärne tõhustamine keerulistes süsteemides on selle C++-s kasutamise teine oluline eelis. Paljude asünkroonsete toimingute tulemuste sujuv kombineerimine on oluline olukordades, kus need annavad tulemusi std::expected tüübid. Lisaks koodi lihtsustamisele tagab see meetod tugeva veakäsitluse. Mitmekülgsemaid ja üldisemaid funktsioone saab luua suvalise arvu funktsioonide kombineerimisel std::expected väärtused koos variadic templates.
Mitmekülgsus magic_apply võimaldab seda kasutada funktsioonidega, mis võtavad vastu mitmesuguseid argumente. Rakendamist muudab veelgi lihtsamaks kasutamine decltype, mis tuletab automaatselt välja kombineeritud funktsioonikutse tagastustüübi. Lisaks saab seda tehnikat laiendada keerukamate ülesannete haldamiseks, sealhulgas liitmiseks std::expected muud tüüpi veaga väärtused või väärtuste muutmine enne nende funktsioonile saatmist. Selle kohandatavuse tõttu saab mustrit kasutada paljude ülesannete jaoks, alates lihtsatest arvutustest kuni keerukate toiminguteni.
Korduma kippuvad küsimused variadic mallide ja std::expected kohta
- Mis on std::expected?
- See on C++ mallitüüp, mis võib sisaldada viga või kehtivat väärtust ja mida kasutatakse vigade haldamiseks.
- Kuidas teeb magic_apply töötada?
- See välistab vajaduse korduvate tõrkekontrollide järele, kombineerides mitmete tulemuste tulemusi std::expected väärtused ja nende edastamine funktsioonile.
- Mis on varieeruvad mallid?
- Muutuvad mallid pakuvad funktsioonide kujundamisel palju vabadust, võimaldades funktsioonidel aktsepteerida suvalise arvu parameetreid.
- Miks kasutada decltype sisse magic_apply?
- Kasutades väärtusi std::expected objektid, et määrata automaatselt välja kutsutava funktsiooni tagastustüüp.
- Is magic_apply suuteline käsitlema erinevaid veatüüpe?
- Jah, selle saab koos toimima panna std::expected väärtused, millel on mitmesugused veatüübid ja mõned näpunäited.
- Milliseid eeliseid annab selle kasutamine std::expected pakkuma?
- Vigade käsitlemisel pakub see väljendusrikkamat ja puhtamat lähenemist kui tavapärasemate tehnikatega, nagu erandid või tagastuskoodid.
- Is std::unexpected osa std::expected?
- Lisaks sellele std::expected, std::unexpected esindab tegelikult vale väärtust.
- Kas asünkroonseid toiminguid saab kasutada koos magic_apply?
- See on tõepoolest kohandatav käsitsemiseks std::expected asünkroonsete operatsioonide poolt tagastatud väärtused.
- Mis on voltimisväljend?
- Siin kasutatakse C++ funktsiooni, mida nimetatakse voltimisväljenduseks, et kontrollida, kas kõik std::expected objektid sisaldavad kehtivaid väärtusi lihtsal viisil.
Kokkuvõte:
C++23-s parandab mitme std::oodatava väärtuse käsitlemise üldise funktsiooni rakendamine oluliselt koodi loetavust ja lihtsustab oluliselt vigade käsitlemist. Funktsioon magic_apply vähendab standardkoodi ja parandab hooldatavust, kasutades variadic malle, et enne töötlemist veenduda, et kõik eeldatavad väärtused on õiged. See meetod pakub paindlikku lahendust, mida saab rakendada erinevates olukordades ning annab kaasaegsele C++ programmeerimisele puhtama ja tõhusama viisi tõrgete käsitlemiseks.