多重嵌套try-catch

Multiply nested try-catch

本文关键字:try-catch 嵌套      更新时间:2023-10-16

我有一个yaml-cpp,它总是转换成std::string,有时也转换成其他东西。例如,如果字符串实际上是"3.14",它也会转换为double。我想先尝试int,然后是double,再是bool,如果不起作用,请转换为std::string。好吧,让我们嵌套那些try-catches:

try {
  const int a = node.as<int>();
  std::cout << "int!" << a << std::endl;
} catch (YAML::BadConversion) {
  try {
    const double a = node.as<double>();
    std::cout << "double!" << a << std::endl;
  } catch (YAML::BadConversion) {
    try {
      const bool a = node.as<bool>();
      std::cout << "bool!" << a << std::endl;
    } catch (YAML::BadConversion) {
      const std::string a = node.as<std::string>();
      std::cout << "string!" << a << std::endl;
    }
  }
}

嗯,越来越深的嵌套告诉我这不是写代码的最佳方式。

关于如何改进这里的设计有什么建议吗?扁平嵌套当然是建议的。

你可以把它放在一个函数中,比如:

template<typename N, typename T>
bool tryParseNode(N& node, T& val) {
  try {
    val = node.as<T>();
    return true;
  } catch (YAML::BadConversion) {
    return false;
  }  
}

然后:

int a;
double d;
bool b;
std::string s;
if (tryParseNode(node, a) {
  std::cout << "int!" << a << std::endl;
}
else if (tryParseNode(node, d) {
  std::cout << "double!" << d << std::endl;
}
else if (tryParseNode(node, b) {
  std::cout << "bool!" << b << std::endl;
}
else if (tryParseNode(node, s) {
  std::cout << "string!" << s << std::endl;
}

尝试其他方法:
转换为字符串,然后尝试布尔等。
单个try中的所有内容都会捕获并忽略异常。

对正常控制流使用异常被认为是不好的做法。在这种情况下,as方法使用"YAML::convert::decode"方法尝试将节点转换为请求的类型,如果失败则返回false,而不是抛出异常。

int anInt;
double aDouble;
bool aBool;
if (YAML::convert <int>::decode (node, anInt))
  std::cout << "int!" << anInt << std::endl;
else
if (YAML::convert <double>::decode (node, aDouble))
    std::cout << "double!" << aDouble << std::endl;
else
if (YAML::convert <bool>::decode (node, aBool))
    std::cout << "double!" << aBool << std::endl;
else
    std::cout << "string!" << node.as <std::string> () << std::endl;

可以进一步简化为

template <typename value_type>
std::optional <value_type> decode (YAML::Node const & Node)
{
    value_type Value;
    if (YAML::convert <value_type>::decode (node, Value))
        return  { Value };
    else
        return {};
}
if (auto anInt = decode <int> (node))
  std::cout << "int!" << *anInt << std::endl;
else
if (auto aDouble = decode <double> (node))
    std::cout << "double!" << *aDouble << std::endl;
else
if (auto aBool = decode <bool> (node))
    std::cout << "double!" << *aBool << std::endl;
else
    std::cout << "string!" << node.as <std::string> () << std::endl;