2016-06-09 13 views
5

Rozważmy parę funkcji poniżej:Jak wymusić inicjalizację statycznej zmiennej lokalnej przed główną?

double MYAPI foo(double x) { 
    return x; 
} 
Register register_foo_([] { 
    return reg(&foo, "foo", ...); // function name repeated used 
}); 

register_foo_ jest zmienną globalną, zainicjowany przed dllmain, której konstruktor przyjmuje lambda że wielokrotnie odwołuje się do nazwy funkcji nad nim dosłownie. Byłoby wspaniale, gdyby kod rejestracyjny mógł poruszać się wewnątrz funkcji powyżej, aby zmniejszyć prawdopodobieństwo popełnienia błędu. Próbowałem:

double MYAPI foo(double x) { 
    static Register register_foo_([] { 
      return reg(&foo, "foo", ...); // static local does not initialize before dllmain 
    }); 
    return x; 
} 

Jeśli powyższy kod działa, to może łatwo przekształcić go w makro sprawia, że ​​korzystanie z __FUNCNAME__. Czy istnieje sposób na wymuszenie inicjowania statycznej zmiennej lokalnej przed dllmain?

+0

Jeśli wywołanie 'foo' nie mieć niepożądane skutki uboczne, można nazwać go na początku' dllmain' – Praetorian

+0

Więc zasadniczo chcesz wywołać funkcję przed głównym? Czy byłam zdezorientowana? – Galik

+0

@Praetorian To, co stara się osiągnąć, to automatyczne śledzenie zarejestrowanej funkcji. Więc wywołanie dllmain nie działa, ponieważ będę musiał wyraźnie wypisać nazwy funkcji. –

Odpowiedz

1

Przypuszczam chcesz osiągnąć składni podobnej do:

DEFINE_FUNC(void, foo, (double x)) { 
    return x; 
} 

... i automatycznie wygeneruje zestaw znaków. To rzeczywiście bardzo proste do zrobienia, jeśli przynieść Register powyższej funkcji, za pomocą oświadczenia:

#define DEFINE_FUNC(Ret, name, args) \ 
    Ret name args;      \ 
    Register register_##name##_([] { \ 
     return reg(&name, #name, ...); \ 
    });        \ 
    Ret name args 
+0

to działa, dziękuję. –

0

Nie, nie ma. To jest twoja odpowiedź.

3

Zmienne statyczne lokalne dla funkcji (metody) są inicjalizowane przy pierwszym użyciu funkcji, w której się znajdują. (Są inicjalizowane zerowo przy ładowaniu programu, następnie inicjalizowane "prawidłowo" za pomocą kodu, gdy funkcja jest wprowadzana po raz pierwszy .) Patrz: answers to this question. Zatem proponowany ruch tego kodu do funkcji zmienia semantykę inicjalizacji i nie zadziała.

Twój pierwotny kod zadziałał, więc najwyraźniej chciałeś przenieść kod wewnątrz funkcji, aby był jakoś związany bliżej umysłu - lub umysłu czytnika kodu - abyś mógł zobaczyć, że twoje ciąg stała nazwa i nazwa funkcji były poprawne. Być może dlatego, że możesz upewnić się, że rejestracja została wykonana. A zatem to, co chcesz osiągnąć, to osiągnąć OSUSZANIE.

Tradycyjny (i jedyny) sposób osiągnięcia tego polega na użyciu makra preprocesora, które rozwija się do wywołania rejestracji i nagłówka funkcji.

Ty zaproponował użycie makra siebie - teraz poszerzyć makro, więc nie tylko generuje funkcję rejestracji, ale również nagłówku funkcji.

+0

Czy istnieje sposób, aby sprawić, że chcę pracować?Koncepcyjnie lista nazw funkcji jest stałą czasową kompilacji. –

+0

@CandyChiu - rozszerzyłem moją odpowiedź, aby odpowiedzieć na twoje pytanie. – davidbak

+0

dzięki. Przegłosowałem twoje wyjaśnienie, ale wybrałem odpowiedź Quentina, ponieważ opublikował kod. –

3

ten uruchamia funkcję przed main(), nie wiem, czy to będzie działać dla dllmain():

#include <iostream> 

int func_before_main() 
{ 
    std::cout << "func_before_main()" << '\n'; 
    // do before main stuff 
    return 0; 
} 

const int dummy = func_before_main(); 

int main() 
{ 
    std::cout << "main()" << '\n'; 
} 

wyjściowy:

func_before_main() 
main() 
+0

Jakikolwiek sposób to zrobić 'const int dummy = func_before_main();' bez jawnego wypisania 'func_before_main'? –

+0

@CandyChiu Prawdopodobnie w zależności od tego, jak wygląda (okropny) MAKRO, które chcesz utworzyć. To może być część tego. – Galik

Powiązane problemy