正在排队 headers 中的呼叫

Queuing a call in headers

目标是允许 header 个文件到 "register" 一个初始化函数,这样 main 就可以迭代这些函数并调用它们。我偶然发现了一个使用 __attribute__ 的解决方案,但它似乎是 GCC-only ().

// header1.h
void myInitializer(){}
REGISTER_THIS(&myInitializer);

// header2.h
void myInitializer2(){}
REGISTER_THIS(&myInitializer2);

// main.cpp
...
for_each_registered_ptr(){ call_ptr(); } // calls myInitializer and myInitializer2
...

是否有通用的解决方案?如果更容易实现,可以使用 类 或类型切换功能。

您可以滥用 static 局部函数来做到这一点,避免静态初始化顺序失败。

init.h 中,我们有这个:

#ifndef INIT_H
#define INIT_H

#include <vector>

// Can be changed to std::function<...> or whatever you need.
typedef void (*init_fn)();

// Returns int so it can easily be used in a variable initializer.
int register_initializer(init_fn fn);
std::vector<init_fn> & get_initializers();

#endif

然后,在init.cpp

#include "init.h"

int register_initializer(init_fn fn)
{
    get_initializers().push_back(fn);

    return 0;
}

std::vector<init_fn> & get_initializers()
{
    static std::vector<init_fn> ip;

    return ip;
}

一些注意事项,在我们继续其余部分之前:

  • static局部只初始化一次,第一次调用函数。
  • "global" 向量有点泄露。除非您向该向量中添加数万个条目,否则这不太可能成为问题。使用后可以随时get_initializers().clear()清空。

我们会像这样使用它,在 a.cpp:

#include <iostream>

#include "init.h"

static void a_init() { std::cout << "a_init()\n"; }

static auto dummy = register_initializer(a_init);

最后,我们(相当简单)main.cpp:

#include "init.h"

int main() {
    for (auto fn : get_initializers()) {
        fn();
    }

    return 0;
}