2013-03-20 28 views
3

我有一個類B派生自類A.聲明一個靜態字段f,並且B可能聲明一個相同名稱的相似字段。以下不工作:在編譯時比較靜態字段指針

struct A { static int f; }; 
struct B : A { static int f; }; // A::f is different from B::f 
struct C : A {}; // A::f is the same as C::f 
BOOST_STATIC_ASSERT((&A::f != &B::f)); 
BOOST_STATIC_ASSERT((&A::f == &C::f)); 

雖然理論上這些斷言可以在編譯時檢查,他們是不允許的,因爲常量表達式不能把地址。

有沒有辦法在編譯時進行這種檢查工作?

+0

具有靜態存儲持續時間的對象的地址是一個常量表達式。 – GManNickG 2013-03-21 00:30:59

+0

@GManNickG:如果靜態變量的定義不在TU中的靜態斷言之前,GCC會抱怨它不是一個常量表達式。如果是,它就會起作用。不知道這是否符合標準。 – 2013-03-21 00:34:58

+0

@ user1131467:Hm,我可以從標準中得到的是§5.19/ 4:「地址常量表達式是std :: nullptr_t類型或指針類型的prvalue核心常量表達式(在上下文需要轉換後)該函數計算的是具有靜態存儲持續時間的對象的地址,函數地址或空指針值。文字常量表達式,引用常量表達式和地址常量表達式統稱爲常量表達式。呃,爲什麼TU很重要? – GManNickG 2013-03-21 00:41:44

回答

5

嘗試將靜態變量的定義放在靜態斷言的範圍內。

這工作得很好用gcc 4.7.2:

struct A { static int f; }; 
struct B : A { static int f; }; 
struct C : A {}; 

int A::f; 
int B::f; 

static_assert(&A::f != &B::f, "B"); 
static_assert(&A::f == &C::f, "C"); 

int main() 
{ 
} 

編譯:

$ g++ -std=gnu++11 test.cpp 
$ ./a.out 
+0

是的,這可能是最好的。謝謝。 – 2013-03-21 16:18:15

+0

不幸的是,它並不適用於我的情況,因爲我需要在其他地方的.cpp文件中進行聲明。 – 2013-03-21 16:23:48