Domanda

Se ho una funzione A(), Sono interessato a trovare un metodo conveniente per creare una funzione B() che ha la stessa identica funzionalità di A(), diverso solo in nome. La nuova funzione sarebbe per un utilizzo una tantum. L'intento è quello di distinguere tra le chiamate alla stessa funzione in un profiler di campionamento un po 'primitivo e la funzione duplicata verrebbe utilizzata solo in questo contesto. Cioè, non toccherebbe mai il codice di produzione e verrà utilizzato solo per armeggiare.

La prima ipotesi sarebbe una macro che dichiara una funzione denominata B e crea una chiamata inserita a A() al suo interno. Il problema qui è che non sono a conoscenza di un metodo in GCC per forzare una chiamata di funzione arbitraria a in linea; Sembra che tutte le opzioni in linea siano per le dichiarazioni delle funzioni piuttosto che per le chiamate.

Potrebbe esserci qualche modo esoterico per farlo con i modelli, o possibilmente ingannando il compilatore in linea. Non sono sicuro che sia possibile. qualche idea? Sfortunatamente il nuovo standard C ++ non è disponibile, se farebbe la differenza.

È stato utile?

Soluzione

Usando modelli

template<int x>
void A()
{
    // ..
}

int main()
{
    A<0>();
    A<1>();
    return 0;
}

Aggiornare

Il compilatore può essere troppo intelligente e creare solo un corpo per <0> e un <1>. Almeno Visual C ++ 2010 lo fa in modalità di rilascio. Per impedirlo, basta utilizzare il parametro modello all'interno del corpo del modello di funzione nei registri o afferma. Per esempio,

#include <iostream>

template<int x>
void A()
{
    ::std::cout << x << std::endl;
    // ..
}

int main()
{
    A<0>();
    A<1>();
    auto v0 = A<0>;
    auto v1 = A<1>;
    ::std::cout << v0 << std::endl;
    ::std::cout << v1 << std::endl;
    ::std::cout << (v0 == v1) << std::endl;
    return 0;
}

Altri suggerimenti

Funziona usando i modelli:

#include <iostream>                                                             

template<typename T>
void foo() {
    static int x = 0;
    std::cout << &x << std::endl;
}

int main(int argc, char **argv) {
    foo<int>();
    foo<float>();
    return 0;
}

Se lo esegui, vedrai due diversi valori stampati, riflettendo il codice generato dal compilatore per entrambe le chiamate, anche se il parametro modello non è utilizzato. nm Sul file oggetto lo conferma.

Se questo è un hack di debug una tantum, allora perché no:

#define A_CONTENT \
    ... // whatever

void A()
{
    A_CONTENT
}

void B()
{
    A_CONTENT
}

...

A();  // Call to A
B();  // Call to B  

Le macro sono generalmente cupe, ma non stiamo parlando di codice di produzione qui, quindi chi se ne frega?

Essendo stato su questa strada da solo, la risposta breve è che anche se si fa in modo che il compilatore emetta due identici duplicati di una funzione, il linker ottimizzante noterà che sono identici e Piegali insieme in un'unica implementazione. (E se hai disattivato l'ottimizzazione nel linker, il tuo profilo non è valido anwyay).

Nel contesto di un profiler di campionamento, ho trovato l'approccio più semplice è fare due piccoli involucri per la funzione:

void Func() { .... }

_declspec(noinline) 
void A_Func( return Func(); }
void B_Func( return Func(); }
void C_Func( return Func(); }

Quindi quando il tuo profiler campiona il callstack, sarai in grado di distinguere tra i diversi callliti di questa funzione in modo molto semplice.

Potresti sempre definire una macro, ad esempio in Cromo Facciamo quanto segue per riutilizzare il codice:

#define CHROMEG_CALLBACK_1(CLASS, RETURN, METHOD, SENDER, ARG1)     \
  static RETURN METHOD ## Thunk(SENDER sender, ARG1 one,            \
                                gpointer userdata) {                \
    return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one); \
  }                                                                 \
                                                                    \
  virtual RETURN METHOD(SENDER, ARG1);

E li chiamiamo come:

 CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent, GdkEventExpose*);

 CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed, GdkEventButton*);

Puoi fare qualcosa di simile per fare quello che volevi. L'esempio sopra ci mostra usando due diverse implementazioni ma con una base di codice comune. Per callback GTK.

È un po 'poco chiaro cosa stai davvero cercando di fare, ma una soluzione davvero brutta sarebbe quella di dichiarare il corpo di una macro e quindi puoi "in linea" questa macro all'interno di qualsiasi funzione ti piaccia.

Inoltre, le macro sono malvagie. Non usarli mai a meno che tu veramente dovere.

Perché ti interessa così tanto di averlo in linea? Se crei una funzione wrapper, ci sono buone probabilità che il compilatore la inlinea comunque. Per lo meno, è improbabile che tu ottenga un frame di funzione costruito.

C ++ 11 ti consente anche di farlo:

void A() {
    ...
}

...

auto B = [] () -> void { A(); };

Ora puoi usare B sintatticamente come se fosse una funzione che avvolge A.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top