Skip to content

Instantly share code, notes, and snippets.

@nutbread
Created January 24, 2016 17:59
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 nutbread/51ce7d4a265c3d98fc4d to your computer and use it in GitHub Desktop.
Save nutbread/51ce7d4a265c3d98fc4d to your computer and use it in GitHub Desktop.
C++ static initialization
#include "StaticInit.hpp"
#if !defined(__cplusplus) || __cplusplus <= 199711L
// No C++11
#define STATIC_INIT_CXX11_NULLPTR 0
#else
// C++11
#define STATIC_INIT_CXX11_NULLPTR nullptr
#endif
bool StaticInit::has_init = false;
StaticInit::Entry* StaticInit::first_entry = STATIC_INIT_CXX11_NULLPTR;
StaticInit::Entry* StaticInit::last_entry = STATIC_INIT_CXX11_NULLPTR;
void StaticInit :: add(InitFunction init, DeinitFunction deinit) {
Entry* e = new Entry();
e->init = init;
e->deinit = deinit;
e->next = STATIC_INIT_CXX11_NULLPTR;
e->previous = last_entry;
if (last_entry == STATIC_INIT_CXX11_NULLPTR) {
first_entry = e;
}
else {
last_entry->next = e;
}
last_entry = e;
}
void StaticInit :: clear_entries() {
Entry* next;
for (Entry* e = first_entry; e != STATIC_INIT_CXX11_NULLPTR; e = next) {
next = e->next;
delete e;
}
last_entry = STATIC_INIT_CXX11_NULLPTR;
first_entry = STATIC_INIT_CXX11_NULLPTR;
}
void StaticInit :: run_init() {
if (has_init) return;
has_init = true;
for (Entry* e = first_entry; e != STATIC_INIT_CXX11_NULLPTR; e = e->next) {
e->init();
}
}
void StaticInit :: run_deinit() {
if (!has_init) return;
has_init = false;
for (Entry* e = last_entry; e != STATIC_INIT_CXX11_NULLPTR; e = e->previous) {
e->deinit();
}
}
#ifndef H_STATIC_INIT__
#define H_STATIC_INIT__
#if !defined(__cplusplus) || __cplusplus <= 199711L
// No C++11
#define STATIC_INIT_CXX11_FINAL
#define STATIC_INIT_CXX11_DELETE_FUNCTION
#define STATIC_INIT_CXX11_FEATURE(...)
#else
// C++11
#define STATIC_INIT_CXX11_FINAL final
#define STATIC_INIT_CXX11_DELETE_FUNCTION = delete
#define STATIC_INIT_CXX11_FEATURE(...) __VA_ARGS__
#endif
#define STATIC_INIT_CONCAT(x,y) STATIC_INIT_CONCAT2(x,y)
#define STATIC_INIT_CONCAT2(x,y) x##y
#define STATIC_INIT(...) \
namespace static_init_namespace_ { \
StaticInitClass< __VA_ARGS__ >::SetupResult STATIC_INIT_CONCAT(static_init_setup_var_,__COUNTER__) = StaticInitClass< __VA_ARGS__ >::setup( \
__VA_ARGS__ :: static_init, \
__VA_ARGS__ :: static_deinit \
); \
}
class StaticInit;
template <typename Type> class StaticInitClass;
class StaticInit STATIC_INIT_CXX11_FINAL {
template <typename Type> friend class StaticInitClass;
private:
typedef void (*InitFunction)();
typedef void (*DeinitFunction)();
struct Entry {
InitFunction init;
DeinitFunction deinit;
Entry* previous;
Entry* next;
};
static bool has_init;
static Entry* first_entry;
static Entry* last_entry;
StaticInit() STATIC_INIT_CXX11_DELETE_FUNCTION;
STATIC_INIT_CXX11_FEATURE(StaticInit(StaticInit&& other) STATIC_INIT_CXX11_DELETE_FUNCTION);
StaticInit(const StaticInit& other) STATIC_INIT_CXX11_DELETE_FUNCTION;
~StaticInit() STATIC_INIT_CXX11_DELETE_FUNCTION;
static void add(InitFunction init, DeinitFunction deinit);
public:
static void clear_entries();
static void run_init();
static void run_deinit();
};
template <typename Type>
class StaticInitClass STATIC_INIT_CXX11_FINAL {
private:
StaticInitClass() STATIC_INIT_CXX11_DELETE_FUNCTION;
STATIC_INIT_CXX11_FEATURE(StaticInitClass(StaticInitClass&& other) STATIC_INIT_CXX11_DELETE_FUNCTION);
StaticInitClass(const StaticInitClass& other) STATIC_INIT_CXX11_DELETE_FUNCTION;
~StaticInitClass() STATIC_INIT_CXX11_DELETE_FUNCTION;
public:
typedef bool SetupResult;
static SetupResult setup(StaticInit::InitFunction init, StaticInit::DeinitFunction deinit) {
StaticInit::add(init, deinit);
return false;
}
};
#undef STATIC_INIT_CXX11_FINAL
#undef STATIC_INIT_CXX11_DELETE_FUNCTION
#undef STATIC_INIT_CXX11_FEATURE
#endif // H_STATIC_INIT__
/*
"%VS140COMNTOOLS%\..\..\VC\bin\vcvars32.bat"
cls && cl /NOLOGO /EHsc StaticInit.cpp StaticTest.cpp /Fe:staticinit_cl.exe > NUL 2> NUL && staticinit_cl.exe
cls && g++ -std=c++11 -o staticinit.exe StaticInit.cpp StaticTest.cpp && staticinit.exe
*/
#include <iostream>
#include "StaticInit.hpp"
class Initable {
public:
template <typename Type, int Value>
class SubClass {
public:
static void static_init() {
std::cout << "static_init2:" << Value << "\n";
}
static void static_deinit() {
std::cout << "static_deinit2:" << Value << "\n";
}
};
static void static_init() {
std::cout << "static_init\n";
}
static void static_deinit() {
std::cout << "static_deinit\n";
}
};
STATIC_INIT(Initable);
STATIC_INIT(Initable::SubClass<int, 0>);
int main(int argc, char** argv) {
StaticInit::run_init();
std::cout << "main\n";
StaticInit::run_deinit();
StaticInit::clear_entries();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment