2017-10-17 104 views
7

noexcept在斯科特邁爾斯的‘有效的現代C++’,他給出了以下功能找到一個數組的大小:使用與constexpr功能

template<typename T, std::size_t N> 
constexpr std::size_t arraySize(T (&)[N]) noexcept 
{ 
    return N; 
} 

什麼目的‘noexcept’在這裏嗎?據我瞭解,noexcept隻影響運行時代碼的生成 - 但我看不到任何可以在運行時調用此函數而不是編譯時的情況?

+0

如果此功能不noexcept,它可能會導致一些類的默認特殊功能的產生不被noexcept,然後導致容器使用悲觀的代碼,以確保異常安全。在這個[例子](https://godbolt.org/g/BKmM3n)中,'struct x'不是默認可構造的,可能不是人們所期望的。 – Oliv

回答

5

在一般情況下,一個模板標記爲constexpr實例化時,可能失去這一地位。如果一組特定的模板參數不允許,那麼該資格將被無聲地刪除,並且生成的函數是一個「常規」函數。

它最有可能這樣的規定,教你一個好習慣。雖然這是真的,一個consexpr功能隱含地假設不拋出,如果函數的constexpr狀態被刪除,但仍然無法與正確noexcept規格干擾。當它被用作輸入到noexcept()運算符的表達式的一部分時。

,如果不是因爲這樣的定義,它會扭曲的,在他們的noexcept()應用程序中使用它的功能異常規範。因爲它被認爲可能在沒有規範的情況下投擲。

由於noexcept()操作是在編譯時計算過,這不是關於代碼生成的所有(如你的話來說)。這更多的是語義正確性的問題,類似於const正確性。

+0

問題在於常量表達式無論如何都被認爲是不拋出。所以應用noexcept運營商ARRAYSIZE的調用將返回true,即使沒有'noexcept'預選賽:http://coliru.stacked-crooked.com/a/991fcd1cb348baef。所以它不被認爲是「沒有規範就可能拋出」。 –

+0

@NirFriedman - (A)如果實例化不允許,可以隱式地撤銷模板函數constexpr狀態。不管這個過分簡單的情況。 (B)這就是爲什麼邁爾斯想要強調一般原則的原因,默認情況下,這個原則是「不排除」正確的。 – StoryTeller

+0

當然,我並不反對你的評論,但是你應該說這是一個很好的習慣,等等。你的實際答案表明它可能干擾正確的'noexcept'規範,但事實並非如此。用戶在這裏問「這裏** noexcept **的目的是什麼**」。我不認爲你在這裏給出的答案是正確的,因爲'noexcept'運算符無論如何都返回true。如果你仍然認爲這是正確的,我希望看到一個例子,從'arraySize'移除'noexcept'會干擾另一個'noexcept'規範的正確性。 –

0

但我看不到任何情況下,可以在運行時調用此函數而不是編譯時間?

例如,簡單地用:

int a[42]; 

std::cout << arraySize(a); 

我們不是一個常量表達式。

要強制constexpr,你必須使用類似:

int a[42]; 
constexpr auto size = arraySize(a); 
std::cout << size; 
+0

'std :: cout << arraySize(a);'not編譯爲'std :: cout << 42;'? –

+0

它可以通過As-If規則(即使您刪除'constexpr'順便說一句),但它不是必需的。 – Jarod42

+0

我認爲'arraySize(a)'是一個常量表達式。某件事是否是一個常量表達式並不取決於它所分配的內容;只是影響它是否確實在編譯時被保證進行評估。無論如何,正如我上面提到的那樣,'noexcept(arraySize(a))'返回true。 –