Quando é que o boost:: elenco lexical para std:: string falha?

Estou a fazer testes de unidade e a tentar ter todo o meu código coberto.

Tenho no meu código algo assim:
template<typename ValueType>
std::string ConvertToStringUsingBoost(ValueType const& v)
{
    try 
    {
        return boost::lexical_cast<std::string, ValueType>(v);
    }
    catch(boost::bad_lexical_cast const& e)
    {
        LOG_ERR("Fail to cast %s to string", e.source_type().name);
        return std::string();
    }
}

estava a ler estes documentos e não consegui encontrar nenhuma informação sobre quando boost::lexical_cast a {2]} podem abrir uma excepção.

Podes ajudar-me com isso?

Se for impossível, apago esta armadilha. Se for possível, Prefiro cobrir isto em testes unitários.

Author: Boann, 2019-05-01

3 answers

Pode falhar, por exemplo, se umdefinido pelo utilizador lançar a conversão:

enum class MyType {};

std::ostream& operator<<( std::ostream&, MyType const& )
{
    throw "error";
}

int main()
{
    try 
    {
        boost::lexical_cast< std::string >( MyType{} );
    }
    catch(...)
    {
        std::cout << "lexical_cast exception";
    }
}

Como você não tem controle sobre o tipo de exceções lançadas por conversões definidas pelo usuário, a captura {[[1]} nem sequer será suficiente. O seu teste de unidade tem de apanhar todas as excepções.

Demonstração Ao Vivo

 7
Author: zett42, 2019-05-01 12:23:10

Não consigo pensar em nenhuma razão para o elenco lexical para o texto lançar {[[0]}, excepto com tipos definidos pelo utilizador. Se o operador de inserção de fluxo ValueType pode definir uma bandeira de erro no fluxo, então isso irá resultar em um bad_lexical_cast. Caso contrário, não.

Pessoalmente eu manteria o catch dentro, mesmo se você estiver apenas convertendo embutidos como ints; não dói, e pode pegar bugs Se você mudar o {[[5]} de alguma forma, ou se houver algum caso de ponta que nem você nem eu tenha considerado; se não estás a lidar com a excepção resultante, vais abortar à hora de execução!

Se está preocupado com a sobrecarga de uma excepção, pode usar try_lexical_cast em vez disso, verifique se ele retorna true em vez de pegar. No entanto, se o operador de inserção de fluxo ValueType pode lançar, então você ainda precisa ser capaz de pegar essa exceção de qualquer maneira.

 10
Author: Lightness Races in Orbit, 2019-05-01 12:57:28

O único seguro e à prova de futuro (eg. sem surpresas desagradáveis após uma atualização de boost ) é prejudicar o seu código com algo (feio) como isto:

template<typename ValueType>
std::string ConvertToStringUsingBoost(ValueType const& v)
{
    try 
    {

#ifdef UNITTEST
      if (unittest == case_fail) {
        throw boost::bad_lexical_cast();
      }
#endif
        return boost::lexical_cast<std::string, ValueType>(v);
    }
    catch(boost::bad_lexical_cast const& e)
    {
        LOG_ERR("Fail to cast %s to string", e.source_type().name);
        return std::string();
    }
}
Agora você deve ser capaz de chegar a essa cobertura de código ~100%!
 1
Author: darune, 2019-05-02 09:30:40