2015-11-27 43 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