C++ C++;在任意翻译单元中,在main之前执行任意代码的习惯用法

C++ C++;在任意翻译单元中,在main之前执行任意代码的习惯用法,c++,idioms,static-block,C++,Idioms,Static Block,我有一个带有main()函数的翻译单元,另一个没有main的翻译单元。假设我只控制第二个,不能触摸第一个 现在,出于我不想讨论的原因,我希望能够在运行main()之前运行一些代码。我知道这可以通过使用函数调用初始化全局变量来实现,但我想隐藏这一点——尽可能少地使用宏(我敢说不使用宏吗?可能不可能,C++中没有合适的静态块) 什么是优雅的,或者说不是很丑陋的方式?更清楚地说,我正在寻找能够提供此功能供多次使用的东西,而不仅仅是让它工作一次的东西。我希望它尽可能接近: // ... at globa

我有一个带有
main()
函数的翻译单元,另一个没有main的翻译单元。假设我只控制第二个,不能触摸第一个

现在,出于我不想讨论的原因,我希望能够在运行
main()
之前运行一些代码。我知道这可以通过使用函数调用初始化全局变量来实现,但我想隐藏这一点——尽可能少地使用宏(我敢说不使用宏吗?可能不可能,C++中没有合适的静态块)

什么是优雅的,或者说不是很丑陋的方式?更清楚地说,我正在寻找能够提供此功能供多次使用的东西,而不仅仅是让它工作一次的东西。我希望它尽可能接近:

// ... at global scope ...
static {
    // my code here
}
附言:这个问题是相关的,但不是同一个问题。这也是出于明确反驳的愿望

注意:是的,我知道静态初始化顺序的失败,不需要提醒我。。。我不是在要求绕过它的东西。显然,静态运行代码需要一些谨慎。

请享受:



请注意,如果不在其他任何地方使用,有时可能不会调用代码(别名“optimized out”)。其中一种情况是将TU编译到静态库中(那么未使用的变量和代码可能不会被拉入可执行文件)。(注意E.马斯科夫斯基)。

这是迄今为止我能想到的最好的答案。这是可行的,但实现起来有点混乱

用法 如果你写:

STATIC_BLOCK {
    std::cout << "Hello static block world!" << std::endl;
}
注意事项:

  • 如果您的编译器不支持
    \uuuuuu计数器\uuuuuuuu
    (因为它是标准的扩展,而不是标准的一部分)-您可以使用
    \uuuuuuu行\uuuuuuuu
    ,这也很有效。GCC和Clang支持
    \uuuu计数器\uuuu
  • \uuuuuuuuuuuuuu属性((未使用))
    是另一个编译器扩展,尽管属性已经进入该语言;例如,见。如果你把它扔了,你会得到警告的
  • 代码是C++ 98(忽略编译器扩展),即不需要支持任何现代C++构造。不幸的是,它不符合C(其中初始值设定项必须是常量)


最初灵感来源于安德烈·亚历山德雷斯库的作品。

闻起来有鱼腥味。。GCC有“<代码>构造函数< /Cord>函数属性”,它可以做你正在寻找的:@ Dean:几件事,但为了讨论的目的——展示C++的能力:-为什么必须在代码>主()/<代码>之前运行?如果它稍后运行,您将如何判断差异?@Barmar:假设我的静态代码小心地将TU的名称添加到某个全局数据结构中(小心地,即不触发失败)。现在
main()。有点整洁,还有其他用途。所以,要使用它,我需要定义对代码其余部分清晰可见的函数;对于_ignoreglobals也一样。我必须小心,总是给他们起不同的名字。我想做得更好…@一点也不。您可以将所有这些内容放在一个编译单元中,放在一个匿名名称空间中。@ein对不起,我不明白。“可见代码”是什么?如果它位于编译单元上的匿名命名空间中(未包含在另一个编译单元中),则定义的标识符在其他地方将不可见(可用)。@einpoklum即使进行了编辑,问题也不清楚。这个答案是正确的。您可以选择代码的哪些部分在TU之外可见。请注意,如果不在其他地方使用,有时可能不会调用代码(别名“optimized out”)。其中一种情况是,当TU被编译到一个静态库中时(那么未使用的变量和代码可能不会被拉入可执行文件中)。@KlitosKyriacou:我没有完全按照你的建议去做,因为这意味着两个静态块会发生冲突。但我确实对它进行了改进,并缩短了impl。谢谢刚刚看到了修改后的代码,虽然它很好,但按照我的建议再做也没有任何好处。
STATIC_BLOCK {
    std::cout << "Hello static block world!" << std::endl;
}
#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__))