C++11 靜態斷言—static_assert


【1】assert 與 #error

我們知道,C++現有的標准中就有assert、#error兩個方法是用來檢查錯誤的,除此而外還有一些第三方的靜態斷言實現。

assert是運行期斷言,它用來發現運行期間的錯誤,不能提前到編譯期發現錯誤,也不具有強制性,也談不上改善編譯信息的可讀性。

既然是運行期檢查,對性能肯定是有影響的,所以經常在發行版本中,assert都會被關掉。

#error可看作是預編譯期斷言(甚至都算不上斷言),僅僅能在預編譯時顯示一個錯誤信息,可以配合#ifdef/ifndef參與預編譯的條件檢查。

由於它無法獲得編譯信息,當然,也就做不了更進一步分析了。

在stastic_assert提交到C++0x標准之前,為了彌補assert和#error的不足,出現了一些第三方解決方案,可以作編譯期的靜態檢查:

例如:BOOST_STATIC_ASSERT和LOKI_STATIC_CHECK,但由於它們都是利用了一些編譯器的隱晦特性實現的trick,可移植性、簡便性都不是太好,還會降低編譯速度,而且功能也不夠完善。

比如BOOST_STATIC_ASSERT就不能定義錯誤提示文字,而LOKI_STATIC_CHECK則要求提示文字滿足C++類型定義的語法。

【2】靜態斷言

C++11中引入了static_assert這個關鍵字,用來做編譯期間的斷言,因此叫作靜態斷言。

語法:

static_assert(常量表達式,"提示字符串")

注解:如果第一個參數常量表達式的值為false,會產生一條編譯錯誤。錯誤位置就是該static_assert語句所在行,第二個參數就是錯誤提示字符串。

【3】總結

使用static_assert,可以在編譯期發現更多的錯誤,用編譯器來強制保證一些契約,幫助我們改善編譯信息的可讀性,尤其是用於模板時。

使用注意點:

[1]使用范圍:static_assert可以用在全局作用域中,命名空間中,類作用域中,函數作用域中,幾乎可以不受限制的使用。

[2]常量表達式:static_assert的斷言表達式的結果必須是在編譯時期可以計算的表達式,即必須是常量表達式,示例如下:

//該static_assert用來確保編譯僅在32位的平台上進行,不支持64位的平台
//該語句可放在文件的開頭處,這樣可以盡早檢查,以節省失敗情況下耗費的編譯時間
static_assert(sizeof(int) == 4, "64-bit code generation is not supported.");

如果讀者使用了變量,則會導致錯誤。示例如下:

int positive(const int n)
{
    static_assert(n > 0, "value must > 0");
    return 0;
}

n作為一個變量,在編譯期根本無法確定值(無能為力),估屬於應用錯誤范疇。

[3]模板參數:編譯器在遇到一個static_assert語句時,通常立刻將其第一個參數作為常量表達式進行演算。

但如果該常量表達式依賴於某些模板參數,則延遲到模板實例化時再進行演算,這就讓檢查模板參數也成為了可能。

示例如下:

 1 #include <cassert>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 template <typename T, typename U> int bit_copy(T& a, U& b)
 6 {
 7     assert(sizeof(b) == sizeof(a));
 8     //static_assert(sizeof(b) == sizeof(a), "template parameter size no equal!");
 9     memcpy(&a, &b, sizeof(b));
10 };
11 
12 int main()
13 {
14     int varA = 0x2468;
15     double varB;
16     bit_copy(varA, varB);
17     getchar();
18     return 0;
19 }

[4]性能方面:由於static_assert是編譯期間斷言,不生成目標代碼,因此static_assert不會造成任何運行期性能損失。

 

good good study, day day up.

順序 選擇 循環 總結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM