2017-04-14 44 views
2

目標是允許頭文件「註冊」初始化函數,以便main可以迭代這些函數並調用它們。我偶然發現了一個使用__attribute__的解決方案,但似乎只有GCC(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 
... 

有沒有一個通用的解決方案呢?如果更容易實現,則可以使用類或類型切換函數。

回答

0

您可以濫用static函數本地執行此操作,避免靜態初始化順序失敗。

init.h,我們有這樣的:

#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 

然後,在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; 
} 

的幾個注意事項,我們進入到休息前:

  • static本地只是初始化一次,第一次調用該函數。
  • 「全局」向量是泄漏種類。除非你爲這個向量添加數以萬計的條目,否則這不太可能會成爲問題。您可以隨時使用get_initializers().clear()將其清空。

我們會使用它像這樣,在a.cpp

#include <iostream> 

#include "init.h" 

static void a_init() { std::cout << "a_init()\n"; } 

static auto dummy = register_initializer(a_init); 

最後,我們有我們的(很簡單)main.cpp

#include "init.h" 

int main() { 
    for (auto fn : get_initializers()) { 
     fn(); 
    } 

    return 0; 
} 
+0

另外值得注意的,該解決方案線程安全只有自C++ 11(魔術靜態) –