Racionalització de la gestió d'errors en C++23
La gestió eficaç dels errors i la gestió dels valors de retorn és essencial en el desenvolupament de C++ actual. El mètode típic de treballar amb funcions que retornen tipus {std::expected} inclou moltes comprovacions i codi de gestió d'errors, que poden complicar la lògica i fer que el codi sigui més difícil de mantenir.
Aquest article investiga l'ús d'un mètode més sofisticat i general per simplificar la gestió d'errors. Per tal de reduir el codi normal i millorar la llegibilitat, investigarem la construcció d'un mètode `magic_apply` que agregui els resultats de molts valors {std::expected} i els passi a una altra funció.
Comandament | Descripció |
---|---|
std::expected | Tipus de plantilla utilitzat en C++ per a la gestió d'errors que té la capacitat d'emmagatzemar tant valors com errors. |
std::unexpected | Quan s'utilitza amb std::expected, representa un valor d'error inesperat. |
template<typename...> | Esbossa una plantilla variada amb una quantitat infinita d'arguments de plantilla que pot acceptar. |
decltype | S'utilitza en la programació de plantilles, especialment per conèixer el tipus d'expressió. |
args.value() | Si un objecte std::expected té un valor, accedeix al valor que hi conté. |
args.has_value() | Verifica si hi ha un valor en un objecte std::expected. |
(... && args.has_value()) | Per determinar si cada objecte std::expected té valors, doblega l'expressió. |
func(args.value()...) | Utilitza els valors de l'objecte std::expected per cridar la funció del mètode. |
return unexpected<Err>(args.error()...) | Retorna un error inesperat que conté els errors dels objectes std::expected. |
Gestió eficaç d'errors mitjançant plantilles variables
El std::expected El tipus s'utilitza als scripts per facilitar la gestió d'errors en C++23. L'objectiu principal és desenvolupar una funció genèrica anomenada magic_apply que pot transmetre la sortida de diversos std::expected valors a una altra funció. En fer això, la tediosa comprovació d'errors que sol ser necessària quan es treballa amb molts std::expected els valors es redueixen. magic_apply és bastant flexible perquè pot prendre qualsevol nombre de std::expected paràmetres utilitzant plantilles variàdiques. Abans de cridar la funció amb el contingut de qualsevol std::expected objecte, la lògica fonamental de magic_apply utilitza una expressió de plec, (... && args.has_value()), per assegurar-se que tot std::expected els objectes tenen valors vàlids.
Aquesta idea s'il·lustra en el primer exemple de guió utilitzant tipus simples com ara int i double. Defineix a compute_all funció que realitza un càlcul bàsic, i getA i getB funcions que tornen std::expected tipus. Si els dos valors de getA i getB són legítims, podem trucar compute_all utilitzant magic_apply; si no, l'error es propaga. En reduir el codi normal, aquest mètode millora la llegibilitat i el manteniment. Una idea similar es presenta en el segon guió, però per destacar la versatilitat de l'enfocament, string tipus i lambda functions s'utilitzen.
Reducció de la complexitat en la gestió d'errors de C++ amb `std::expected}
Script C++23 utilitzant plantilles variàdiques
#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;
}
Combinant diferents valors de resultats de {std::expected} C++23
Script C++23 utilitzant funcions Lambda
#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;
}
Millora de la gestió d'errors de C++ amb plantilles Variadic
La capacitat de std::expected millorar molt el maneig d'errors en sistemes complexos és un altre avantatge crucial d'utilitzar-lo en C++. La combinació perfecta dels resultats de moltes accions asíncrones és essencial en situacions en què cedeixen std::expected tipus. A més de simplificar el codi, aquest mètode garanteix un fort maneig d'errors. Es poden crear funcions més versàtils i genèriques combinant un nombre arbitrari de std::expected valors amb variadic templates.
La versatilitat de magic_apply permet utilitzar-lo amb funcions que accepten diversos tipus d'arguments. La implementació es fa més senzilla mitjançant l'ús decltype, que dedueix automàticament el tipus de retorn de la crida de funció combinada. A més, aquesta tècnica es pot ampliar per gestionar tasques més complexes, inclosa la fusió std::expected valors amb altres tipus d'error o alterar els valors abans d'enviar-los a la funció. A causa de la seva adaptabilitat, el patró es pot utilitzar per a una àmplia gamma de tasques, des de càlculs senzills fins a operacions complexes.
Preguntes freqüents sobre Plantilles Variadic i std::expected
- Què és std::expected?
- És un tipus de plantilla C++ que pot contenir un error o un valor vàlid i s'utilitza per a la gestió d'errors.
- Com ho fa magic_apply treballar?
- Elimina la necessitat de comprovacions repetides d'errors combinant els resultats de nombrosos std::expected valors i passar-los a una funció.
- Què són les plantilles variàdiques?
- Les plantilles variables ofereixen una gran llibertat en el disseny de funcions, ja que permeten que les funcions acceptin un nombre arbitrari de paràmetres.
- Per què utilitzar decltype en magic_apply?
- Utilitzant els valors de la std::expected objectes per determinar automàticament el tipus de retorn de la funció que es crida.
- És magic_apply capaç de gestionar diversos tipus d'error?
- Sí, es pot fer que funcioni std::expected valors que tenen diversos tipus d'error amb alguns ajustaments.
- Quins avantatges té utilitzar std::expected oferta?
- Quan es tracta d'errors, ofereix un enfocament més expressiu i més net que amb tècniques més convencionals com les excepcions o els codis de retorn.
- És std::unexpected part de std::expected?
- A més de std::expected, std::unexpected de fet, representa un valor incorrecte.
- Es poden utilitzar accions asíncrones amb magic_apply?
- De fet, és adaptable al maneig std::expected valors retornats per operacions asíncrones.
- Què és una expressió de plec?
- Aquí, la característica en C++ anomenada expressió de plec s'utilitza per comprovar si tot std::expected els objectes contenen valors vàlids d'una manera senzilla.
Conclusió:
En C++23, la implementació d'una funció genèrica per gestionar diversos valors std::esperats millora molt la llegibilitat del codi i simplifica molt el maneig d'errors. La funció magic_apply redueix el codi normal i millora el manteniment mitjançant l'ús de plantilles variades per assegurar-se que tots els valors previstos són correctes abans de processar-los. Aquest mètode ofereix una solució flexible que es pot aplicar a diferents situacions i ofereix a la programació C++ moderna una manera més neta i eficaç de gestionar els errors.