在C++中实现对include的能力发现的地道做法
两次我都遇到这样的需求:在一个被包含的C++文件中向全局能力列表添加某些能力,我在想实现的最佳方式是什么。
我有两个用例:
测试发现
我想在多个文件中定义一组测试,然后在 test.cpp 中执行如下操作:
#include "module1/test.h"
#include "module2/test.h"
#include "test.h"
int main() {
for (const auto& test : autodiscover()) {
// or `for (const auto& test : TESTS)`
test();
}
}
(包括错误报告以及其他信息。)
数据库仓库预处理语句设置
我有一个项目,由一堆不同的可执行文件组成,可以想象成微服务(尽管并非完全如此),它们在某种程度上都在同一个数据库上工作。出于下面不展开说明的原因,每条对数据库执行的语句都在可执行启动时被 PREPAREd提前处理。 This sentence is kept as: "出于下面不展开说明的原因,每条对数据库执行的语句都在可执行启动时被 PREPAREd提前处理。" 这是通过一个 repo::init() 函数来完成的。
就目前而言,该函数有一个静态定义的 prepareSomething()s数组,并按顺序调用它们。
这很不幸,因为这意味着我不能把仓库拆分成多个翻译单元,而我也希望能这样做。
比如说,我希望更新 updateCustomerEmail() 不会引发对 monthly-earnings-report 可执行文件的重新编译,尽管后者根本没有调用前者。
为此,我希望仓库的每个片段都把它的 prepareXYZ()s添加到一个全局的“要初始化的项”列表中,这样当主可执行文件调用 repo::init() 时,能执行的语句都已经准备好,其他的都不会再被准备。
我觉得我想做的事情是可能的,甚至可能很容易实现,因为一切都能在编译时获得,但我找不到实现的方法。我的所有谷歌搜索都只把我引导到服务发现,并让我去使用网络层,显然这并不是我要解决的问题。
解决方案
关于自注册,请参考Google Test的做法:从
TEST(Fix, Tst)
{ my code }
它会生成类似这样的代码
class Fix_Tst_Test{
void TestBody() override;
static ::testing::TestInfo *const test_info_ __attribute__((unused));
};
::testing::TestInfo *const Fix_Tst_Test::test_info_
= ::testing::internal::MakeAndRegisterTestInfo(
"Fix",
"Tst",
// other parameters
);
void Fix_Tst_Test::TestBody()
{ my code }
注册是由用于初始化静态成员的函数来完成的,该函数在调用 main() 之前执行。