我有一個類X
,在x.h
中聲明並在x.cpp
中定義,它必須在靜態初始化階段運行一些代碼(在集中位置註冊一些類的元數據)宏INIT(X)
。對於X
的任何子類Y
(在y.h
中的聲明,包括x.h
,在y.cpp
中的定義)都是相同的 - 它必須在全局範圍內運行INIT(Y)
。現在我想創建一個靜態檢查,如果每個子類已經初始化。另外我不知道我會鏈接多少個X
子類。當子類沒有使用另一個宏時,C++宏將失敗
我要定義x.h
宏如果存在的X
一個(或X
任何其他後裔),將產生一個編譯器錯誤已經不叫INIT(SubClass)
。怎麼做?
要求:
- C++ 11。
- 如果需要,可能需要在
subclass.cpp
文件中調用它。 - 可能需要將其全部定義在
subclass.cpp
中。 - 我想支持的編譯器至少有
gcc
和msvc
。 - 它應該不會在導入
x.h
的someotherclass.cpp
中生成錯誤,除非它定義了X
的子類。 - 該錯誤可能是任何種類的編譯器錯誤,它不一定是
#error
,例如,未定義的變量也很好。 - 此宏的代碼可能需要對
X
類進行其他更改,但不包括其任何子類。 INIT
必須在放入subclass.cpp
之後的任何地方都有效。
定義一個新的基類的X
一個虛擬抽象方法,如果只有我沒有不修改任何X
的子類的放在那裏的聲明和定義在INIT
的要求會工作。
下面是該設計的模板代碼,其中INIT
僅用於計算鏈接的X
子類+ 1的數量。只要它有效,/*???*/
可用任何東西代替。
x.h
:
#include <functional>
int &someGlobalInt();
class XInit {
public:
XInit(std::function<void()> init) {
init();
}
};
#define INIT(cls) static XInit X_INIT_ ## cls = XInit([](){ \
++someGlobalInt(); \
/*???*/ \
})
class X {
/*???*/
};
/*???*/
x.cpp
:
#include "x.h"
int &someGlobalInt() {
static int x = 0;
return x;
}
INIT(X); // error without it
y.h
:
#include "x.h"
class Y: public X {};
y.cpp
:
#include "y.h"
INIT(Y); // error without it
main.cpp
:
#include <cstdio>
#include "x.h"
// no error, since no new X subclass is defined
int main() {
printf("%d\n", someGlobalInt()); // should print "2"
return 0;
}
fyi,根據標準項目以雙下劃線開頭保留。 '17.6.3.3.2全局名稱[global.names]' ' - 包含雙下劃線_ _的每個名稱或以下劃線開頭並帶有大寫字母(2.12)的字符保留給實現以供任何用途。' – lcs 2014-10-06 18:19:35
感謝您的信息,我會改變它。但主要問題仍然存在。 – Xilexio 2014-10-06 19:43:14
@Xilexio我現在沒有時間,但如果今晚晚些時候這個問題仍然沒有答案,我會盡力爲你提供一個解決方案。 – Serge 2014-10-06 19:52:12