我有一个类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