Когда не удается повысить :: lexical_cast на std :: string? - PullRequest
9 голосов
/ 01 мая 2019

Я пишу модульные тесты и пытаюсь покрыть весь мой код.

В моем коде есть что-то вроде этого:

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();
    }
}

Я читал эти документы и не смог найти никакой информации о том, когда boost::lexical_cast до std::string может выдать исключение.

Не могли бы вы помочь мне с этим?

Если это невозможно, я просто удалю эту попытку. Если это возможно, я бы предпочел рассмотреть это в модульном тестировании.

Ответы [ 3 ]

10 голосов
/ 01 мая 2019

Я не могу придумать ни одной причины, по которой лексическое приведение к строке должно вызывать bad_lexical_cast, за исключением пользовательских типов. Если оператор вставки потока ValueType может установить флаг ошибки в потоке, то это приведет к bad_lexical_cast. В противном случае нет.

Лично я бы оставил catch, даже если вы просто конвертируете встроенные модули, такие как int s; это не повредит, и может поймать ошибки, если вы каким-либо образом измените lexical_cast, или если есть какой-то крайний случай, который ни вы, ни я не рассмотрели; если вы не обработаете полученное исключение, вы получите прерывание во время выполнения!

Если вы беспокоитесь об издержках исключения, вы можете вместо этого использовать try_lexical_cast и проверить, что оно возвращает true, а не перехват. Однако, если оператор вставки потока ValueType может выдать команду, вам все равно потребуется возможность перехватить это исключение.

7 голосов
/ 01 мая 2019

Может произойти сбой, например, если определенный пользователем конверсионный бросок:

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";
    }
}

Поскольку у вас нет контроля над типом исключений, генерируемых пользовательскими преобразованиями, перехват boost::bad_lexical_cast будет даже недостаточным. Ваш юнит-тест должен отловить все исключения.

Демонстрация в реальном времени

1 голос
/ 01 мая 2019

Единственный безопасный и устойчивый к будущему (например, никаких неприятных сюрпризов после обновления ) - это ухудшить ваш код чем-то (безобразным), подобным этому:

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();
    }
}

Теперь вы должны быть в состоянии получить 100% покрытие кода!

...