/ / Come ottenere un nome di funzione passato nei parametri? - c ++, argomenti

Come ottenere un nome di funzione passato nei parametri? - c ++, argomenti

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 № 1

Non 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