2017-04-14 1 views
2

目的は、ヘッダーファイルが初期化関数を「登録」して、メインがそれらの関数を繰り返し処理して呼び出すことができるようにすることです。私は__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.cppで、その後

#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.h

、我々は、この持っている

#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 localは、関数が呼び出されたときに初めて一度だけ初期化されます。
  • "グローバル"ベクトルは一種のリークです。このベクトルに何万ものエントリを追加しない限り、これは問題になることはまずありません。あなたはいつでも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(マジックスタティックス)以降のスレッドセーフです。 –

関連する問題