2015-11-27 36 views
92

在Scott Schurr的谈话"Introducing constexpr" at CppCon的最后,他问道:“有没有办法毒化一个功能?”他接着解释说,这可以(在一个非标准的方式虽然)这样做:在C++中“毒害一个函数”意味着什么?

  1. 把一个throwconstexpr功能
  2. 声明一个悬而未决的extern const char*
  3. throw
  4. 引用未解决 extern

我感觉到,我有点在这里我的深度,但我很好奇:

  • “毒功能”是什么意思?
  • 他概述的技术的重要性/有用性是什么?
+1

从来没有听说过这个词,请以简明的例子来澄清! –

+6

@πάνταῥεῖ,我刚澄清。这个术语'在小圈子中广为人知' – SergeyA

+4

他正在讨论确保每次调用'constexpr'函数时都会在编译时进行评估。 –

回答

100

一般而言,它指的是使功能不可用,例如,如果您想禁止在程序中使用动态分配,您可能会“毒化”malloc函数,因此无法使用它。

在视频中,他以更具体的方式使用它,如果您阅读显示的幻灯片时显示的幻灯片清晰,他说中毒函数时会显示“仅强制编译时?”的方法?

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

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

由于未定义的符号在函数的编译时调用中不是“odr-used”,因此实际上编译器不会创建对该符号的引用,所以它可以是未定义的。

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

其中一个原因可能会有用的是,某些操作的编译时版本的效率不如它可能高。对constexpr函数允许的表达式类型有限制(特别是在C++ 11中,在C++ 14中删除了一些限制)。因此,您可能有两个版本的函数用于执行计算,一个是最优的,但使用constexpr函数中不允许的表达式,另一个是有效的constexpr函数,但如果在运行时调用时表现不佳,时间。您可能会损害次优性能,以确保它永远不会用于运行时调用,从而确保运行时调用使用更高效的(非constexpr)版本。

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

+1

我没看过幻灯片的文字,但我没有看到他使用的术语的联系。现在很明显,你已经解释了它,但当时我没有看到它。非常感谢这个优秀的答案 - 我只是喜欢这个网站。 –

+0

@PravasiMeet,问你自己的问题,不要劫持别人关于不同事情的问题的评论。一个简单的解决方案是将其定义为在每个翻译单元中删除,或者用您自己的定义引用未定义的符号来替换它。 –

18

'中毒'标识符意味着'中毒'后对标识符的任何引用都是一个硬编译器错误。例如,可以使用这种技术进行硬弃用(函数已被弃用,从不使用它!)。

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

+0

是的,但不完全符合那次谈话的意义。 –

+0

@ T.C。,好吧,我应该在回答之前观看它:) – SergeyA