Effektivisera felhantering i C++23
Att effektivt hantera misstag och hantera avkastningsvärden är avgörande i dagens C++-utveckling. Den typiska metoden att arbeta med funktioner som returnerar {std::expected}-typer inkluderar många kontroller och felhanteringskod, vilket kan komplicera logiken och göra koden svårare att underhålla.
Denna artikel undersöker användningen av en mer sofistikerad och generell metod för att förenkla felhantering. För att minska koden och förbättra läsbarheten kommer vi att undersöka att konstruera en `magic_apply`-metod som aggregerar resultaten av många {std::expected}-värden och skickar dem till en annan funktion.
Kommando | Beskrivning |
---|---|
std::expected | En malltyp som används i C++ för felhantering som har möjlighet att lagra både värden och fel. |
std::unexpected | När det används med std::expected representerar det ett oväntat felvärde. |
template<typename...> | Skisserar en variadisk mall med en oändlig mängd mallargument som den kan acceptera. |
decltype | Används vid mallprogrammering, speciellt för att ta reda på typen av uttryck. |
args.value() | Om ett std::expected objekt har ett värde, kommer åt värdet som finns i det. |
args.has_value() | Verifierar om ett värde finns i ett std::expected objekt. |
(... && args.has_value()) | För att avgöra om varje std::expected objekt har värden, vik uttrycket. |
func(args.value()...) | Använder värdena för std::expected-objekten för att anropa metoden func. |
return unexpected<Err>(args.error()...) | Returnerar ett oväntat fel som innehåller felen från std::expected-objekten. |
Effektiv felhantering med hjälp av variabelmallar
De typ används i skripten för att underlätta felhanteringen i C++23. Huvudmålet är att utveckla en generisk funktion som kallas som kan överföra resultatet från flera värden till en annan funktion. Genom att göra detta, den tråkiga felkontrollen som vanligtvis är nödvändig när man arbetar med många std::expected värden reduceras. är ganska flexibel eftersom det kan ta hur många som helst parametrar genom att använda variadiska mallar. Innan du anropar funktionen med innehållet i ev objekt, den grundläggande logiken i magic_apply använder ett veckuttryck, , för att se till att allt objekt har giltiga värden.
Denna idé illustreras i det första skriptexemplet med enkla typer som t.ex och . Den definierar en funktion som utför en grundläggande beräkning, och getA och funktioner som återkommer typer. Om båda värdena från och getB är legitima kan vi ringa använder ; om inte, sprids felet. Genom att reducera boilerplate-koden förbättrar denna metod läsbarheten och underhållbarheten. En liknande idé presenteras i det andra manuset, men för att belysa tillvägagångssättets mångsidighet, typer och lambda functions används.
Minska komplexiteten i C++ felhantering med `std::expected}
C++23-skript som använder Variadic-mallar
#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;
}
Kombinera olika {std::expected} resultat C++23 värden
C++23-skript som använder lambdafunktioner
#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;
}
Förbättra C++-felhantering med Variadic-mallar
Kapaciteten hos att avsevärt förbättra felhanteringen i invecklade system är en annan avgörande fördel med att använda det i C++. Att kombinera resultaten av många asynkrona åtgärder sömlöst är viktigt i situationer när de ger resultat typer. Förutom att göra koden enklare garanterar denna metod en stark felhantering. Mer mångsidiga och generiska funktioner kan skapas genom att kombinera ett godtyckligt antal värden med variadic templates.
Mångsidigheten hos gör att den kan användas med funktioner som tar in en mängd olika argumenttyper. Implementeringen görs ytterligare enklare genom att använda , som automatiskt härleder returtypen för det kombinerade funktionsanropet. Dessutom kan denna teknik utökas för att hantera mer komplicerade uppgifter, inklusive sammanslagning värden med andra feltyper eller ändra värdena innan de skickas till funktionen. På grund av dess anpassningsförmåga kan mönstret användas för ett brett spektrum av uppgifter, från enkla beräkningar till komplexa operationer.
Vanliga frågor om Variadic-mallar och std::expected
- Vad är ?
- Det är en C++-malltyp som kan innehålla ett fel eller ett giltigt värde och används för felhantering.
- Hur gör arbete?
- Det eliminerar behovet av upprepade felkontroller genom att kombinera resultaten från många värden och skicka dem till en funktion.
- Vad är variadiska mallar?
- Variabla mallar erbjuder en stor del av friheten i funktionsdesign genom att göra det möjligt för funktioner att acceptera ett godtyckligt antal parametrar.
- Varför använda i ?
- Att använda värdena för objekt för att automatiskt bestämma returtypen för den funktion som anropas.
- är kan hantera olika feltyper?
- Ja, den kan göras för att fungera med värden har olika feltyper med några få justeringar.
- Vilka fördelar använder man erbjuda?
- Vid hantering av misstag erbjuder det ett mer uttrycksfullt och renare tillvägagångssätt än med mer konventionella tekniker som undantag eller returkoder.
- är del av ?
- Förutom , representerar i själva verket ett felaktigt värde.
- Kan asynkrona åtgärder användas med ?
- Den är verkligen anpassningsbar att hantera värden som returneras av asynkrona operationer.
- Vad är ett veckuttryck?
- Här används funktionen i C++ som kallas fold expression för att kontrollera om alla objekt innehåller giltiga värden på ett enkelt sätt.
I C++23 förbättrar implementering av en generisk funktion för att hantera flera std::expected värden avsevärt kodens läsbarhet och förenklar felhanteringen avsevärt. Funktionen magic_apply reducerar boilerplate-koden och förbättrar underhållsbarheten genom att använda variadic-mallar för att säkerställa att alla förväntade värden är korrekta före bearbetning. Denna metod erbjuder en flexibel lösning som kan appliceras på olika situationer och ger modern C++-programmering ett renare och mer effektivt sätt att hantera fel.