在C ++中“毒化一个函数”意味着什么?

在斯科特•舒尔(Scott Schurr) 在CppCon的“介绍constexpr ”的演讲结束时 ,他问道:“有没有办法让一个function中毒呢? 然后他解释说,这可以通过以下方式完成(尽pipe以非标准方式):

  1. 投入一个constexpr函数
  2. 声明一个无法parsing的extern const char*
  3. throw在引用未解决的extern

我觉得我在这里有一点点深刻,但我很好奇:

  • 什么意思是“毒化一个function”?
  • 他概括的技术的重要性/有用性是什么?

一般来说,它指的是使一个function无法使用,例如,如果你想禁止在程序中使用dynamic分配,你可以“毒化” malloc函数,所以它不能被使用。

在video中,他以更具体的方式使用了video,如果您阅读显示的幻灯片时显示的是“强制编译时的方式?

所以他说的是“毒化”函数使其在运行时不可调用,所以它只能在常量expression式中调用。 该技术是在函数中有一个分支,在编译时上下文中调用该分支时,该分支将包含会导致错误的内容。

在constexpr函数中允许使用throwexpression式,只要在函数的编译时调用中永远不会到达throwexpression式(因为在编译时不能抛出exception,这是一个固有的dynamic操作,就像分配内存一样)。 因此,在编译时调用期间不会使用引用未定义符号的throwexpression式(因为这会导致编译失败),并且在运行时不能使用,因为未定义的符号会导致链接器错误。

因为未定义的符号在函数的编译时调用中不是“odr-used”,所以实际上编译器不会创build对符号的引用,所以没有定义。

这有用吗? 他正在展示如何去做,不一定说这是一个好主意或广泛的用途。 如果由于某种原因你需要这样做,那么他的技术可能会解决你的问题。 如果你不需要它,你不需要担心。

其中一个可能有用的原因是某些操作的编译时版本效率不高。 在constexpr函数中允许的expression式的types是有限制的(特别是在C ++ 11中,在C ++ 14中删除了一些限制)。 所以你可能有两个版本的函数来执行计算,一个是最优的,但是使用在constexpr函数中不允许的expression式,一个是有效的constexpr函数,但是如果在run-时间。 您可能会中毒次优,以确保它永远不会用于运行时调用,确保运行时调用使用更高效的(非constexpr)版本。

注意在编译时使用的constexpr函数的性能并不重要,因为它无论如何都没有运行时间的开销。 它可能会让编译器做额外的工作,从而减慢编译速度,但不会有任何运行时性能成本。

“中毒”标识符意味着在“中毒”之后对标识符的任何引用都是硬编译器错误。 例如,这种技术可能被用于硬弃用(function被弃用,从不使用它!)。

在海湾合作委员会传统上有一个这样的编译: #pragma GCC poison