Skip to content

Instantly share code, notes, and snippets.

@aguinet
Last active February 28, 2017 07:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aguinet/a4f62dc5fbaf7aae083618520851c4e0 to your computer and use it in GitHub Desktop.
Save aguinet/a4f62dc5fbaf7aae083618520851c4e0 to your computer and use it in GitHub Desktop.
Custom static C++ initializers list
// 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