这是迄今为止我能想到的最好的。它有效,但实现有点丑陋。
用法
如果你写:
STATIC_BLOCK {
std::cout << "Hello static block world!" << std::endl;
}
此代码将在您的main()
. 但是,请注意,在开始std::cout
之前写入main()
实际上并不是一个好主意。
笔记:
- 您必须用花括号将静态块代码括起来(不需要尾随分号;感谢@KlitosKyriacou 的建议)。
- 如果您不使用花括号,则可能会出现难以理解的错误消息。
- C++中不保证静态代码的相对执行顺序。
执行
静态块实现涉及一个虚拟变量。为了确保我们不会与其他一些虚拟变量(例如来自另一个静态块 - 或其他任何地方)发生冲突,我们需要一些宏机制。
#define CONCATENATE(s1, s2) s1##s2
#define EXPAND_THEN_CONCATENATE(s1, s2) CONCATENATE(s1, s2)
#define STATIC_BLOCK_IMPL2(function_name,var_name) \
static void function_name(); \
static int var_name __attribute((unused)) = (function_name(), 0) ; \
static void function_name()
#define STATIC_BLOCK_IMPL1(prefix) \
STATIC_BLOCK_IMPL2(CONCATENATE_FOR_STATIC_BLOCK(prefix,_fn),CONCATENATE_FOR_STATIC_BLOCK(prefix,_var))
#define STATIC_BLOCK STATIC_BLOCK_IMPL1(EXPAND_THEN_CONCATENATE(static_block_,__COUNTER__))
笔记:
- 如果您的编译器不支持
__COUNTER__
(因为它是标准的扩展,而不是标准的一部分) - 您可以使用__LINE__
,它也可以。GCC 和 Clang 支持__COUNTER__
。
__attribute__((unused))
是另一个编译器扩展,尽管属性已经进入语言;例如,请参阅此讨论。如果你放下它,你会得到一个警告。
- 代码是 C++98(忽略编译器扩展),即您不需要任何支持的现代 C++ 构造。不幸的是,它不符合 C 的条件(其中初始化程序必须是常量)。
最初灵感来自 Andrei Alexandrescu 的SCOPE_EXIT
把戏。