依然是研究 AirSim 的代码,今天在里面发现了如上的一小部分代码,其中 noexept 并不是作为一个函数的修饰符,而是作为一个运算符来使用了。

 

原本 noexcept(expression) 是用于标明一个函数是否必定不会发生异常的修饰符,其中 expression 是一个常量表达式,如果这个表达式为 true ,表明函数是不会发生异常的,如果发生了可以直接终止程序。

对于没有说明 noexcept 的函数,大部分都是作为 noexcept(false) ,也就是可能发生任何异常来处理,除了以下的特例:

内部没有可能产生异常的代码的 构造函数(默认,复制,移动)、赋值运算符(复制,移动)、析构函数。

 

这是一般 noexcept 的用法,而上面的代码,则是noexcept作为运算符的另一种用法。

作为运算符的 noexcept(expression) 可以返回 expression 运行时是否可能发生异常。它会将 expression 分成一个个的子表达式,将它们一个个按以下规则分析:

  1. 如果是一个函数调用(包括运算符重载、隐式类型转换等隐含调用),则按上面的规则来确认 onexcept 是否为true
  2. 如果是 throw 语句的话必然是 false
  3. 如果是 dynamic_cast 也为 false (std::bad_cast)
  4. 如果是 typeid 运算符也为 false (std::bad_typeid)
  5. 如果是构造元素个数非常量的 new 语句也为 false (std::bad_array_new_length)

最后进行一个与运算混合各个子表达式的结果,就是 expression 是否可能发生异常的结果了。

 

PS:更详细的说其实算是对那个表达式会有一个潜在异常(potential exceptions)的列表,最后按照那个列表里有没有元素来判断的…

PS2:配合模板真是看得人一愣一愣的…

PS3:顺便一说… std::declval<T> 是一个返回 T 类型右值的函数,不过只能用在编译时decltype之类并不关心其返回值实际数据,而是关心类型的场合。算是 (T*)nullptr 之类相对丑陋的强制类型转换的替代品吧~~