Last active
February 28, 2017 07:32
-
-
Save aguinet/a4f62dc5fbaf7aae083618520851c4e0 to your computer and use it in GitHub Desktop.
Custom static C++ initializers list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The idea is to statically create a list of initializers that would be | |
// launched when the "user" wants. This question has been asked by @lapinhib0u | |
// for the shell-factory project (https://github.com/gdelugre/shell-factory). | |
// The idea is that some classes might define initializers that needs to be | |
// launched at the beggining of the shell code, and each class might define | |
// whether it needs such initializer or not. Even if the whole code ends up in | |
// one compilation unit in the end, the construction of the initializer list is | |
// splitted accross various include files. | |
// | |
// Here is below one implementation of this that uses the __COUNTER__ macro. | |
// Indeed, the main issue of declaring a "splitted" compile time "list" is to | |
// know the name of the last element of this list. | |
// | |
// This works with clang and gcc but I'm not quite happy with this. Indeed: | |
// * this uses the __COUNTER__, which AFAIK isn't standard | |
// * this relies on the ability of the compiler to inline the recursive | |
// template calls to Initializers::run. This works with clang and gcc, but | |
// still. Shell codes are generated in the end :) | |
// | |
// Any idea to make this better is welcome! | |
#include <cstdlib> | |
#include <cstdio> | |
namespace { | |
struct Initializers | |
{ | |
template <size_t N> | |
static void init() | |
{ | |
} | |
template <size_t N> | |
__attribute__((always_inline)) static void run() | |
{ | |
run<N-1>(); | |
init<N>(); | |
} | |
}; | |
template <> | |
void Initializers::run<__COUNTER__>() | |
{ | |
} | |
#define MAKE_INIT(Type) \ | |
template <>\ | |
void Initializers::init<__COUNTER__>()\ | |
{\ | |
Type::init();\ | |
}\ | |
#define RUN_INITS \ | |
Initializers::run<__COUNTER__> | |
struct TypeA | |
{ | |
static void init() | |
{ | |
puts("Type A init"); | |
} | |
}; | |
struct TypeB | |
{ | |
static void init() | |
{ | |
puts("Type B init"); | |
} | |
}; | |
MAKE_INIT(TypeA); | |
MAKE_INIT(TypeB); | |
} | |
int main() | |
{ | |
RUN_INITS(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment