Pregunta

Si tengo una función A(), Estoy interesado en encontrar un método conveniente para crear una función B() que tiene exactamente la misma funcionalidad que A(), diferiendo solo en nombre. La nueva función sería para un uso único. La intención es diferenciar entre llamadas a la misma función en un perfilador de muestreo algo primitivo, y la función duplicada solo se utilizaría en este contexto. Es decir, nunca tocaría el código de producción y solo se usaría para jugar.

La primera suposición sería una macro que declara una función llamada B y crea una llamada en línea para A() dentro de eso. El problema aquí es que no conozco un método en GCC para forzar una llamada de función arbitraria a la línea; Parece que todas las opciones de enlinición son para declaraciones de funciones en lugar de llamadas.

Puede haber alguna forma esotérica de hacerlo con plantillas, o posiblemente engañando al compilador para que enlinee. No estoy seguro de que sea posible. ¿Alguna idea? Desafortunadamente, el nuevo estándar C ++ no está disponible, si marcaría la diferencia.

¿Fue útil?

Solución

Usando plantillas

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

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

Actualizar

El compilador puede ser demasiado inteligente y crear solo un cuerpo para A <0> y A <1>. Al menos Visual C ++ 2010 lo hace en modo de lanzamiento. Para evitarlo, simplemente use el parámetro de plantilla dentro del cuerpo de la plantilla de función en registros o afirma. Por ejemplo,

#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;
}

Otros consejos

Esto funciona usando plantillas:

#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;
}

Si ejecuta eso, verá dos valores diferentes impresos, lo que refleja el código generado por el compilador para ambas llamadas, a pesar de que el parámetro de plantilla no se usa. nm En el archivo de objeto confirma esto.

Si este es un hack de depuración único, entonces, ¿por qué no:

#define A_CONTENT \
    ... // whatever

void A()
{
    A_CONTENT
}

void B()
{
    A_CONTENT
}

...

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

Las macros son generalmente sombrías, pero no estamos hablando del código de producción aquí, entonces, ¿a quién le importa?

Habiendo estado en este camino yo mismo, la respuesta corta es que incluso si obtienes el compilador para emitir dos duplicados idénticos de una función, el enlazador de optimización notará que son idénticos y Doblarlos de nuevo juntos en una implementación. (Y si ha desactivado la optimización en el enlazador, entonces su perfil no es válido Anwyay).

En el contexto de un perfilador de muestreo, descubrí que el enfoque más fácil es hacer dos pequeños envoltorios para la función: en su lugar:

void Func() { .... }

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

Luego, cuando su Profiler muestree el CallStack, podrá diferenciar entre los diferentes lugares de llamadas de esta función de una manera muy directa.

Siempre puedes definir una macro, por ejemplo en Cromo Hacemos lo siguiente para reutilizar el código:

#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);

Y los llamamos como:

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

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

Puedes hacer algo similar para hacer lo que querías. El ejemplo anterior nos muestra usando dos implementaciones diferentes pero con una base de código común. Para devoluciones de llamada GTK.

No está claro lo que realmente estás tratando de hacer, pero una solución realmente fea sería declarar el cuerpo de una macro y luego puedes "en línea" esta macro dentro de las funciones que quieras.

Además, las macros son malvadas. Nunca los uses a menos que tú De Verdad tengo que.

¿Por qué te importa tanto la incrustación? Si crea una función de envoltorio, hay una buena posibilidad de que el compilador lo esté en línea de todos modos. Por lo menos, es poco probable que se construya un marco de funciones.

C ++ 11 también te permite hacer esto:

void A() {
    ...
}

...

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

Ahora puede usar B sintácticamente como si fuera una función envolviendo A.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top