Simplificando o tratamento de erros em C++23
O tratamento eficaz de erros e o gerenciamento de valores de retorno são essenciais no desenvolvimento atual de C++. O método típico de trabalhar com funções que retornam tipos {std::expected} inclui muitas verificações e código de tratamento de erros, o que pode complicar a lógica e tornar o código mais difícil de manter.
Este artigo investiga o uso de um método mais sofisticado e geral para simplificar o gerenciamento de erros. Para reduzir o código padrão e melhorar a legibilidade, investigaremos a construção de um método `magic_apply` que agrega os resultados de muitos valores {std::expected} e os passa para outra função.
Comando | Descrição |
---|---|
std::expected | Um tipo de modelo usado em C++ para tratamento de erros que tem a capacidade de armazenar valores e erros. |
std::unexpected | Quando usado com std::expected, representa um valor de erro inesperado. |
template<typename...> | Descreve um modelo variado com uma quantidade infinita de argumentos de modelo que ele pode aceitar. |
decltype | Usado na programação de templates, principalmente para descobrir o tipo de expressão. |
args.value() | Se um objeto std::expected tiver um valor, acessa o valor contido nele. |
args.has_value() | Verifica se um valor está presente em um objeto std::expected. |
(... && args.has_value()) | Para determinar se cada objeto std::expected tem valores, dobre a expressão. |
func(args.value()...) | Usa os valores dos objetos std::expected para chamar o método func. |
return unexpected<Err>(args.error()...) | Retorna um erro inesperado contendo os erros dos objetos std::expected. |
Gerenciamento eficaz de erros usando modelos variáveis
O type é usado nos scripts para facilitar o tratamento de erros em C++23. O objetivo principal é desenvolver uma função genérica chamada que pode transmitir a saída de vários valores para outra função. Ao fazer isso, a tediosa verificação de erros que normalmente é necessária ao trabalhar com muitos std::expected valores são reduzidos. é bastante flexível porque pode levar qualquer número de parâmetros utilizando modelos variados. Antes de chamar a função com o conteúdo de qualquer objeto, a lógica fundamental da magic_apply emprega uma expressão de dobra, , para garantir que tudo objetos têm valores válidos.
Essa ideia é ilustrada no primeiro exemplo de script usando tipos simples como e . Ele define um função que realiza um cálculo básico, e getA e funções que retornam tipos. Se ambos os valores de e getB são legítimos, podemos chamar usando ; caso contrário, o erro é propagado. Ao reduzir o código clichê, esse método melhora a legibilidade e a facilidade de manutenção. Ideia semelhante é apresentada no segundo roteiro, mas para destacar a versatilidade da abordagem, tipos e lambda functions são usados.
Reduzindo a complexidade no tratamento de erros C++ com `std::expected}
Script C++23 usando modelos variados
#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;
}
Combinando valores C++23 de resultados {std::expected} diferentes
Script C++23 usando funções 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;
}
Melhorando o tratamento de erros C++ com modelos variados
A capacidade de melhorar significativamente o tratamento de erros em sistemas complexos é outro benefício crucial de empregá-lo em C++. Combinar perfeitamente os resultados de muitas ações assíncronas é essencial em situações em que elas produzem tipos. Além de tornar o código mais simples, esse método garante um forte tratamento de erros. Funções mais versáteis e genéricas podem ser criadas combinando um número arbitrário de valores com variadic templates.
A versatilidade de permite que ele seja usado com funções que aceitam vários tipos de argumentos. A implementação é ainda mais simplificada utilizando , que deduz automaticamente o tipo de retorno da chamada de função combinada. Além disso, esta técnica pode ser expandida para gerenciar tarefas mais complexas, incluindo a fusão valores com outros tipos de erro ou alterando os valores antes de enviá-los para a função. Devido à sua adaptabilidade, o padrão pode ser usado para uma ampla gama de tarefas, desde cálculos simples até operações complexas.
Perguntas frequentes sobre modelos variados e std::expected
- O que é ?
- É um tipo de modelo C++ que pode conter um erro ou um valor válido e é usado para gerenciamento de erros.
- Como é que trabalhar?
- Elimina a necessidade de repetidas verificações de erros, combinando os resultados de numerosos valores e passá-los para uma função.
- O que são modelos variados?
- Os modelos de variáveis oferecem uma grande liberdade no design de funções, permitindo que as funções aceitem um número arbitrário de parâmetros.
- Por que usar em ?
- Utilizando os valores do objetos para determinar automaticamente o tipo de retorno da função que está sendo chamada.
- É capaz de lidar com vários tipos de erros?
- Sim, pode ser feito para funcionar com valores com vários tipos de erros com alguns ajustes.
- Quais vantagens a utilização oferecer?
- Ao lidar com erros, oferece uma abordagem mais expressiva e limpa do que técnicas mais convencionais, como exceções ou códigos de retorno.
- É parte de ?
- Além de , na verdade, representa um valor incorreto.
- As ações assíncronas podem ser utilizadas com ?
- Na verdade, é adaptável para lidar valores retornados por operações assíncronas.
- O que é uma expressão dobrada?
- Aqui, o recurso em C++ chamado expressão fold é usado para verificar se todos objetos contêm valores válidos de maneira simples.
Em C++23, implementar uma função genérica para lidar com vários valores std::expected melhora muito a legibilidade do código e simplifica muito o tratamento de erros. A função magic_apply reduz o código clichê e melhora a capacidade de manutenção usando modelos variados para garantir que todos os valores previstos estejam corretos antes do processamento. Este método oferece uma solução flexível que pode ser aplicada a diferentes situações e oferece à programação C++ moderna uma maneira mais limpa e eficaz de lidar com falhas.