標籤:parameter ret amp template required while UI int anti
C98或C99中的庫為:<cassert> 或<assert.h>
運行時斷言,故明思議是當程式在啟動並執行時候才作為判決,可以認為是對參數的有效性的判斷。
而靜態斷言,是對參數的條件判斷提前做了,在先行編譯的時候進行完成的。如:
//demo1.cpp#include <cassert>using namespace std;char *arrayAolloc(int n){ assert(n>0); return new char [n];}int main(){ char * a = arrayAolloc(0); return 0;}//gcc demo1.cpp -omain
assert(n>0); 該條件只會在當arrayAlloc的時候才會進行判斷,要根據程式的傳參來處理其有效性。
如下:
template <typename T, typename U>int bit_copy(T& a, U& b){ assert(sizeof(b) == sizeof(a)); memcpy(&a, &b, sizeof(b));};
上述很明顯示,T與U並非是同一個類型,但是assert同樣不參在編譯的時候檢查出來,只有當程式運行後才可以判斷到。
下面作一個改進,定義一個宏:
#define assert_static(e) do { enum { assert_static__ = 1/(e)}; } while (0)template <typename T, typename U>int bit_copy(T& a, U& b){ assert_static(sizeof(b) == sizeof(a)); memcpy(&a, &b, sizeof(b));};
這樣我們在編譯時間宏替換的過程中,就可以檢查到,1/0是一個錯誤的文法,就直接拋出來了。
在C11中,庫函數中已經存在了這樣的函數 static_assert(expr, desc);
如果在編譯的時候expr==false, 那麼將會拋出desc的資訊,這樣就可以直接從代碼中排查出硬性的錯誤,不必等到程式運行後,才檢查出來。
static_assert是編譯時間的斷言,其使用範圍不像assert一樣受到限制。
static_assert的斷言參數expr必須是已知的常量,該常量在編譯時間就可以判斷出來。
無法在編譯時間判斷的常量,不可用static_assert來斷言,如下:
template <typename T, typename U>int bit_copy(T& a, U& b){ //assert_static(sizeof(b) == sizeof(a)); static_assert(sizeof(b) == sizeof(a), "the parameters of bit_copy must have the same width."); memcpy(&a, &b, sizeof(b));};int positive(const int n){ static_assert(n > 0, "abcd:");}$ g++ -std=c++11 -c 2.2.8.cpp2.2.8.cpp: 在函數‘int positive(int)’中:2.2.8.cpp:20:2: 錯誤:靜態斷言中出現非常量條件 static_assert(n > 0, "abcd:"); ^2.2.8.cpp:20:2: 錯誤:‘n’不是一個常量運算式2.2.8.cpp: In instantiation of ‘int bit_copy(T&, U&) [with T = int; U = double]’:2.2.8.cpp:25:15: required from here2.2.8.cpp:15:2: 錯誤:static assertion failed: the parameters of bit_copy must have the same width. static_assert(sizeof(b) == sizeof(a), "the parameters of bit_copy must have the same width.");
C++11 新特性,運行時斷言與靜態斷言