Quando é que o boost:: elenco lexical para std:: string falha?
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.
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
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 int
s; 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.
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%!