-
-
Save nutbread/51ce7d4a265c3d98fc4d to your computer and use it in GitHub Desktop.
C++ static initialization
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
#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(); | |
} | |
} | |
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
#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__ | |
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
/* | |
"%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