AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 76978692
Accepted
Mikhail T.
Mikhail T.
Asked: 2023-08-25 23:47:05 +0800 CST2023-08-25 23:47:05 +0800 CST 2023-08-25 23:47:05 +0800 CST

Como um construtor pode sinalizar ao chamador se uma exceção que está lançando é fatal?

  • 772

Estou lidando com um aplicativo que precisa ler mais de 10 arquivos CSV (de tipos diferentes) como entrada. Os dados são lidos em um contêiner – std::mapou vector.

Anteriormente, cada tipo tinha sua própria função de análise, e estou trabalhando para unificá-la em uma única função padronizada: economizar na manutenção futura do código e fornecer relatórios de erros uniformes para arquivos corrompidos.

Esta função lê cada linha, discerne se o tipo de contêiner tem o conceito de a key(like map) e usa emplacepara essas e emplace_backpara as outras (like vector).

A única expectativa da classe de valor do contêiner é que seu construtor possa instanciar a partir de uma linha CSV. Qualquer exceção do construtor é um erro fatal - o nome do arquivo de entrada e o número da linha são relatados e o programa é encerrado:

try {
        if constexpr (is_associative_container<Container>(NULL)) {
                result->emplace(typename Container::key_type(
                    key, keylen), value);
        } else {
                result->emplace_back(value);
        }
} catch (const std::exception &e) {
        fprintf(stderr, "%s:%zd: %s\n", path, line, e.what());
        goto failure;
}

Tudo isso funciona e estou feliz - cerca de 75% da análise de CSV agora é feita por esta função.

Agora estou enfrentando o quarto restante dos arquivos CSV, que são menos simples: porque certas linhas neles requerem tratamento especial e seu conteúdo não deve ser armazenado no contêiner.

Como o value_typeconstrutor do sinaliza para a função que a exceção que ela está lançando não deve ser considerada fatal? Uma maneira é escolher uma das exceções padrão ( std::bad_function_call?) como sinal, mas isso significaria que a exceção escolhida não deve ocorrer inesperadamente - o que não é confiável...

Algo mais?

c++
  • 3 3 respostas
  • 74 Views

3 respostas

  • Voted
  1. Best Answer
    463035818_is_not_an_ai
    2023-08-26T00:13:18+08:002023-08-26T00:13:18+08:00

    Uma edição de pergunta coincidiu com a redação desta resposta. A resposta original está abaixo.

    Como o construtor do value_type pode sinalizar para a função que a exceção que ele está lançando não deve ser considerada fatal?

    Observe que no seu código atual você já faz uma distinção entre exceções herdadas de std::exceptione aquelas que não herdam de std::exception. Um bom estilo é herdar todas as exceções, std::exceptionmas a realidade geralmente é diferente.

    Você poderia introduzir algum tipo especial de exceção a ser lançada:

                try {
                     //...
                } catch (const non_fatal_exception &e) {
                        // do something
                } catch (...) { // all other exceptions are "fatal"
                        fprintf(stderr, "%s:%zd: %s\n", path, line, e.what());
                        goto failure;
                }
    

    Resposta antiga sobre especificações de exceção dinâmicas...

    Conforme mencionado nos comentários, as especificações de exceção dinâmica foram removidas do C++ 17.

    Antes do C++ 17, uma função que lançava uma exceção não listada na especificação de exceção fazia o seguinte (de cppreference ):

    Se a função lançar uma exceção do tipo não listado em sua especificação de exceção, a função std::unexpectedserá chamada. A função padrão chama std::terminate, mas pode ser substituída por uma função fornecida pelo usuário (via std::set_unexpected) que pode chamar std::terminateou lançar uma exceção. Se a exceção lançada std::unexpectedfor aceita pela especificação de exceção, o desenrolamento da pilha continuará normalmente. Se não for, mas std::bad_exceptionfor permitido pela especificação da exceção, std::bad_exceptionserá lançado. Caso contrário, std::terminateé chamado.

    Não há saída a menos que você conheça alguma exceção que seria aceita pela especificação da exceção, mas em geral você não sabe disso. Não estou ciente de deduzir as exceções "permitidas" no código genérico. De qualquer forma, o recurso foi removido. E, em certo sentido, já era "fatal" lançar uma exceção não listada na especificação da exceção, não é algo que você precise fazer extra.

    • 1
  2. Mooing Duck
    2023-08-26T00:29:38+08:002023-08-26T00:29:38+08:00

    Se for normal que a linha não entre no contêiner, então esse não é um fluxo excepcional e você não deveria usar exceções. A função deve receber outro parâmetro:Function<bool(RowData)> shouldInsertIntoContainer

    • 0
  3. Mikhail T.
    2023-08-26T01:32:54+08:002023-08-26T01:32:54+08:00

    Ok, com base na minha própria inclinação - e nas sugestões de @Eljay (comentário) e @ 463035818_is_not_an_ai (resposta aceita), modifiquei o código assim:

            try {
                if constexpr (is_associative_container<Container>(NULL)) {
                    result->emplace(typename Container::key_type(
                        key, keylen), value);
                } else {
                    result->emplace_back(value);
                }
            } catch (const std::string &message) {
                /*
                 * Allow constructors to fail without aborting the
                 * parsing of the file by throwing an std::string.
                 * If the string is not empty, output it to stderr.
                 */
                if (!message.empty())
                    fprintf(stderr, "%s:%zd: %s\n", path, line,
                        message.c_str());
                continue;
            } catch (const std::exception &e) {
                fprintf(stderr, "%s:%zd: %s\n", path, line, e.what());
                goto failure;
            } catch (...) {
                fprintf(stderr, "%s:%zd: internal error while "
                    "emplacing into %s\n",
                    path, line, typeid(Container).name());
                goto failure;
            }
    
    • 0

relate perguntas

  • Por que os compiladores perdem a vetorização aqui?

  • Erro de compilação usando CMake com biblioteca [fechada]

  • Erro lançado toda vez que tento executar o premake

  • Como criar um tipo de octeto semelhante a std::byte em C++?

  • Somente operações bit a bit para std::byte em C++ 17?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve