Ho appena trovato qualcosa come ottenere il nome della funzione corrente o ottenere il nome del chiamante, alcune varianti per ottenere o chiamare il nome come stringa.
Quello che voglio è ottenere il nome della funzione che ho passato in argomenti. Come questo:
void Bar()
{
//do something
}
void Foo(void (*f)())
{
//this will output: Foo
std::cout << __FUNCTION__ << std::endl;
//How do I get the name passed to f? (in this case: Bar)
}
int main()
{
Foo(Bar);
return 0;
}
Grazie.
Modifica: ecco un codice estremamente vicino per quello che sto cercando di seguire il suggerimento di @Jose.
thread_local const char * m_last_function_called = "";
#define register_function() {m_last_function_called = __FUNCTION__;}
inline const char * get_last_function() { return m_last_function_called; }
// const char * g_last_function_called = "";
// #define register_function() { g_last_function_called = __FUNCTION__; }
// inline const char * get_last_function() { return g_last_function_called; }
void print_last_func()
{
static std::mutex sync_cout;
std::lock_guard<std::mutex> l(sync_cout);
std::cout << get_last_function() << std::endl;
}
bool interruptFooTimer = false;
int FooTimer()
{
register_function();
print_last_func();
std::cout << "FooTimer.start" << std::endl;
int t = 0;
while(t<10)
{
if(interruptFooTimer==false)
{
sleep(1);
t++;
std::cout << "tt=" << t << std::endl;
}
else
{
return -1;
}
}
std::cout << "FooTimer.end" << std::endl;
return 0;
}
void CallTrd(int (*f)())
{
std::thread TrdTemp(f);
TrdTemp.detach();
TrdTemp.~thread();
print_last_func();
}
int main()
{
CallTrd(FooTimer);
print_last_func();
int c = 0;
while(c<15)
{
if(c==7) {interruptFooTimer=true;}
sleep(1);
c++;
std::cout << "c=" << c << std::endl;
print_last_func();
}
return 0;
}
Osservare che io chiamo print_last_func () inmomenti diversi e tutti ottengono lo stesso valore inizializzato nella variabile. Questo codice di esempio chiama un thread senza usare join () perché non posso aspettare che il thread finisca e anche implementare il detach () e il ~ thread per terminare il mio programma senza eccezioni.Il interruptFooTimer che sto usando per tranquillamente "termina" "il mio filo. Cosa mi manca per ottenere il valore globale acquisito in register_function ??
risposte:
1 per risposta № 1Non puoi. __FUNCTION__
è espanso dal compilatore durante il tempo di compilazione. Non è possibile ottenere queste informazioni in runtime.
0 per risposta № 2
Usa una macro helper:
#define Foo(x) FooHelper(#x, x)
void FooHelper(const char *f_name, void (*f)())
{
cout << f_name;
}
0 per risposta № 3
Come altri hanno già notato, non puoi farlo direttamente.
Prima di tutto vorrei usare std :: Funzione invece di un puntatore a funzione grezza e std :: string per mantenere il nome della funzione.
Vorrei anche avvolgerli in questo modo:
template<class T>
struct Functor
{
std::function<T> functor_;
std::string name_;
Functor(const std::function<T>& functor, const std::string& name)
: functor_(functor)
, name_(name)
{}
};
Puoi quindi usarlo in questo modo:
void Bar()
{
// do something
}
void Foo(const Functor<void()>& functor)
{
}
int main()
{
Functor<void()> f(std::bind(Bar), "Bar");
Foo(f);
return 0;
}
Puoi anche usare una macro per semplificarti le cose.
#define FUNCTOR(t, x, ...) Functor<t>(std::bind(&x, __VA_ARGS__), #x)
Quale può essere usato in questo modo:
int main()
{
auto f = FUNCTOR(void(), Bar);
return 0;
}
Nota che se segui questo approccio il nome della funzione potrebbe non essere lo stesso di quello che usi __FUNCTION__
i rendimenti.
0 per risposta № 4
Non so perché lo vuoi fare, ma spero che sia per scopi di debug. Ovviamente il percorso più semplice è passare il __FUNCTION__
come argomento come sottolineato. Ma dal mio punto di vista, c'è un approccio migliore.
Ad esempio, potresti avere una variabile globale:
thread_local const char * g_last_function_called = "";
#define register_function() { g_last_function_called = __FUNCTION__; }
inline const char * get_last_function() { return g_last_function_called; }
void Bar()
{
register_function()
}
void Foo(void (*f)())
{
std::cout << get_last_function() << std::endl;
}
void my_func_that_doesnt_accept_nulls(CClass * p)
{
if (p == nullptr)
{
std::cout << " function" << get_last_function();
std::cout << "passed a bad pointer, fix it" << std::endl;
return;
}
}
Ovviamente, questo non ti darà il risultato giusto in multi-thread, ma puoi probabilmente correggerlo usando un thread_local const char * g_last_function_called = ""
variabile.
Il motivo per cui mi piace questo metodo è perché tuttodevi fare per rimuoverlo dal tuo progetto è solo un semplice "trova e sostituisci" di register_function (), e dal momento che usa semplici puntatori, non c'è modo di rallentare il tuo programma.
Modifica: questo è il modo in cui sto testando il codice
void print_last_func()
{
static std::mutex sync_cout;
std::lock_guard<std::mutex> l(sync_cout);
std::cout << get_last_function() << std::endl;
}
void HelloWorld1()
{
register_function();
print_last_func();
}
void HelloWorld2()
{
register_function();
print_last_func();
}
int main()
{
register_function();
std::thread t1(HelloWorld1);
std::thread t2(HelloWorld2);
print_last_func();
t1.join();
t2.join();
return 0;
}
Ottengo: HelloWorld1, HelloWorld2 e main