【问题标题】:When does boost::lexical_cast to std::string fail?boost::lexical_cast 到 std::string 什么时候失败?
【发布时间】:2019-05-01 11:30:42
【问题描述】:

我正在编写单元测试并试图覆盖我的所有代码。

我的代码中有这样的内容:

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

我正在阅读these docs,但找不到任何有关boost::lexical_caststd::string 何时可以引发异常的信息。

你能帮帮我吗?

如果不可能,我会简单地删除这个 try-catch。如果可能的话,我更愿意在单元测试中介绍这一点。

【问题讨论】:

  • 你可能可以使用boost::conversion::try_lexical_convert函数来避免抛出bad_lexical_cast异常。

标签: c++ boost lexical-cast


【解决方案1】:

我想不出任何理由将词法转换为字符串抛出bad_lexical_cast,除非是用户定义的类型。如果ValueType 流插入运算符可以在流上设置错误标志,那么这将导致bad_lexical_cast。否则,不。

我个人会保留catch,即使您只是转换像ints 这样的内置函数;如果您以某种方式更改lexical_cast,或者如果您和我都没有考虑过某些极端情况,它不会受到伤害,并且可能会捕获错误;如果您不处理产生的异常,您将在运行时中止!

如果您担心异常的开销,可以改用try_lexical_cast 并检查它是否返回true 而不是捕获。但是,如果 ValueType 流插入运算符可以抛出,那么您仍然需要能够捕获该异常。

【讨论】:

  • 我每次出门都会收到bad_weather_cast
  • @SombreroChicken 切换到 overcast 以获得预期行为
  • 由于有catch,在函数中添加noexcept说明符可以使调用代码更小/更快。
  • 确实,查看提升源,其中bad_lexical_cast 是文件lexical_cast_empty_input_test.cpp 中的预期结果 - 当转换为字符串时,预期为空字符串。找不到字符串转换抛出的实例。
【解决方案2】:

例如,如果 用户定义 转换抛出:

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 甚至还不够。您的单元测试必须捕获所有异常。

Live Demo

【讨论】:

  • 嗯,我读到这个问题是关于 bad_lexical_cast 的,但这是一个很好的观点
  • 在 OPs 代码中,他专门只捕获了boost::bad_lexical_cast
  • @darune 问题标题和描述是通用的:“当 boost::lexical_cast 到 std::string 可以抛出异常时”。 OP 没有问什么时候可以抛出boost::bad_lexical_cast。代码示例只附带一个问题,它可能是错误的。
【解决方案3】:

唯一安全且面向未来的(例如,更新 后不会出现令人讨厌的意外)是用这样的东西(丑陋)损害您的代码:

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% 的代码覆盖率!

【讨论】:

  • 语法无效
  • 是的,这主要是我所针对的概念。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
相关资源
最近更新 更多