在C ++中“毒化一个函数”意味着什么?
在斯科特•舒尔(Scott Schurr) 在CppCon的“介绍constexpr
”的演讲结束时 ,他问道:“有没有办法让一个function中毒呢? 然后他解释说,这可以通过以下方式完成(尽pipe以非标准方式):
- 投入一个
constexpr
函数 - 声明一个无法parsing的
extern const char*
-
throw
在引用未解决的extern
我觉得我在这里有一点点深刻,但我很好奇:
- 什么意思是“毒化一个function”?
- 他概括的技术的重要性/有用性是什么?
一般来说,它指的是使一个function无法使用,例如,如果你想禁止在程序中使用dynamic分配,你可以“毒化” malloc
函数,所以它不能被使用。
在video中,他以更具体的方式使用了video,如果您阅读显示的幻灯片时显示的是“强制编译时的方式?
所以他说的是“毒化”函数使其在运行时不可调用,所以它只能在常量expression式中调用。 该技术是在函数中有一个分支,在编译时上下文中调用该分支时,该分支将包含会导致错误的内容。
在constexpr函数中允许使用throw
expression式,只要在函数的编译时调用中永远不会到达throw
expression式(因为在编译时不能抛出exception,这是一个固有的dynamic操作,就像分配内存一样)。 因此,在编译时调用期间不会使用引用未定义符号的throwexpression式(因为这会导致编译失败),并且在运行时不能使用,因为未定义的符号会导致链接器错误。
因为未定义的符号在函数的编译时调用中不是“odr-used”,所以实际上编译器不会创build对符号的引用,所以没有定义。
这有用吗? 他正在展示如何去做,不一定说这是一个好主意或广泛的用途。 如果由于某种原因你需要这样做,那么他的技术可能会解决你的问题。 如果你不需要它,你不需要担心。
其中一个可能有用的原因是某些操作的编译时版本效率不高。 在constexpr函数中允许的expression式的types是有限制的(特别是在C ++ 11中,在C ++ 14中删除了一些限制)。 所以你可能有两个版本的函数来执行计算,一个是最优的,但是使用在constexpr函数中不允许的expression式,一个是有效的constexpr函数,但是如果在run-时间。 您可能会中毒次优,以确保它永远不会用于运行时调用,确保运行时调用使用更高效的(非constexpr)版本。
注意在编译时使用的constexpr函数的性能并不重要,因为它无论如何都没有运行时间的开销。 它可能会让编译器做额外的工作,从而减慢编译速度,但不会有任何运行时性能成本。
“中毒”标识符意味着在“中毒”之后对标识符的任何引用都是硬编译器错误。 例如,这种技术可能被用于硬弃用(function被弃用,从不使用它!)。
在海湾合作委员会传统上有一个这样的编译: #pragma GCC poison
。