The goal is to allow header files to "register" an initializer function so that main can just iterate over those functions and call them. I've stumbled upon a solution which uses __attribute__
, but it seems to be GCC-only (https://stackoverflow.com/a/37082249/7867841).
// 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
...
Is there a universal solution to this? Functions can be switched with classes or types if that's easier to implement.
You can abuse static
function locals to do this, avoiding the static initialization order fiasco.
In init.h
, we have this:
#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
Then, in 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;
}
A few notes, before we move on to the rest:
static
local is only initialized once, the first time the function is called.get_initializers().clear()
to empty it out after using it.We'd use it like so, in a.cpp
:
#include <iostream>
#include "init.h"
static void a_init() { std::cout << "a_init()\n"; }
static auto dummy = register_initializer(a_init);
And, finally, we have our (rather simple) main.cpp
:
#include "init.h"
int main() {
for (auto fn : get_initializers()) {
fn();
}
return 0;
}