C++ 格式化异常消息字符串的小技巧

发布时间:2019-06-27 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了C++ 格式化异常消息字符串的小技巧脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

Make C++ Exceptions More Informative

相比其他语言,C++的异常是比较PRimITive的,没有语言层面的stack-trace, STL里的异常类也很有限. 然而作为Modern C++,异常还是必不可少的,虽然有很多人主张pure error code based error handling, 但是这样会介入control-flow, 也使代码更加复杂. 然而异常的一个不足在于它的constructor的参数是一个字符串而已,很多时候我们希望在异常抛出的时候提供一些context information,比如变量的值等等. 最近看faceBook的folly C++ 库得到一点启发,所以动手写了一些utility template functions 来包装异常抛出,同时提供格式化的异常信息。具体代码如下

在异常构造函数中传入格式化字符串提供上下文信息

template<typename TExcept, typename ... TArgs>
  void Throw(TArgs&&... rest) {

    throw TExcept(ToStr(std::forward<TArgs>(rest)...).c_str());
  }

  template<typename TExcept, typename TVal, typename ... TRest>
  void ThrowOnFalse(TVal&& value, TRest&&... rest) {
    if (!value) {
      Throw<TExcept>(std::forward<TRest>(rest)...);
    }
  }

  // enable exception with formatted string message 
  template<typename E>
  void Throwf(const char* fmt, ...) {
    char buf[DEFAULT_BUFSIZE];
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(buf, sizeof buf, fmt, ap);
    va_end(ap);
    throw E(std::string(buf).c_str());
  }

让异常信息自动包含出错位置

一个macro就搞定了,如下


#define THROW_FMT(EXCEPTION, fmt, ...) 
   Throwf<EXCEPTION>("[Error] %s:%d:%s:n" fmt "n", __FILE__, __LINE__, __func__, ##__VA_ARGS__ )

#define CHECK_THROW(cond,E) 
  if(!(cond)) 
   Throwf<E>("[CheckFailure] %s:%d:%s:n" "Failed Condition: " #cond , __FILE__,__LINE__,__func__ )
  

另外,定义Custom Exception也是一个很枯燥的事情,很多时候就是继承std::exception 或者 std::runtime_error 所以写了一个Macro来简化自定义异常类的构造

#define NEW_RT_EXCEPTION(E) class E: public std::runtime_error
    {
  public:
   explicit E(const char* m): runtime_error(m){}
   explicit E(const std::string& m): runtime_error(m){}
   virtual ~E(){}
    }

在之前的代码中,注意到ToStr() 函数,实际上是一个模板函数,用来做 Convert everything to string,是一个受folly启发写的一个简化版本. 其实就是很多函数特化而已,部分代码如下

字符串转换模板函数

/// <summary>
  /// Everything conversion to string
  /// </summary>
  template <typename TSrc>
std::string ToStr(TSrc src) {
  std::stringstream ss;
  ss << src;
  return ss.str();
}

template<>
inline
std::string ToStr(double src){
  char buf[DEFAULT_BUFSIZE];
  d2string(buf, sizeof buf, src);
  return std::string(buf);
}
// variadic template version 
template<typename TSrc, typename ... TRest>
std::string ToStr(TSrc src, TRest&&... rest) {
  std::string r = ToStr(src);
  r += ToStr(std::forward<TRest>(rest)...);
  return r;
}

脚本宝典总结

以上是脚本宝典为你收集整理的C++ 格式化异常消息字符串的小技巧全部内容,希望文章能够帮你解决C++ 格式化异常消息字符串的小技巧所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。