¿Existe una “referencia” útil que se pueda adquirir desde una std::function de vuelta a la función/lambada almacenada?
En C, si uno quiere conocer/adquirir una referencia útil de vuelta a un callback/otra función, puede hacerlo fácilmente casteando la función a un void*
. Más tarde, por ejemplo durante la depuración, se puede examinar el puntero y rastrearlo hasta la función original (por ejemplo, a través de la salida del mapa del compilador o incluso del depurador del editor).
Este tipo de información es muy útil al utilizar “migas de pan” – por ejemplo, un búfer circular de void*
s – para depurar el flujo de una aplicación.
En C++, con std::function
, es posible obtener un puntero sin procesar a través de la función miembro target
, sin embargo, esto solo funciona si se conoce de antemano el tipo preciso del destino almacenado (es decir, una función C estándar); sin embargo, cuando se almacenan funciones anónimas, esto deja de ser el caso, ya que el destino ya no es una simple void()
para una std::function
y, por lo tanto, devolverá nullptr
.
En vista de lo anterior, ¿cuál es la siguiente mejor referencia a la que se puede acceder al destino almacenado de tal manera que se pueda usar, preferiblemente, después de que la ejecución de la aplicación haya finalizado o mientras se encuentra pausada con el depurador adjunto?
¿Se puede adquirir el destino a través de alguna magia de plantilla, conservando aún la semántica/usabilidad de std::function
dentro del código de la biblioteca? Esto debería incluir la captura de funciones anónimas y funciones C puras.
Algunas notas:
– No estoy preguntando cómo hacer depuración
– No estoy preguntando cómo se podría capturar información de depuración desde el destino almacenado; imagina que esto es una biblioteca en lugar de código de cliente.
davy.ai
Si el tipo exacto del objetivo almacenado en una
std::function
no se conoce de antemano, y la función miembrotarget<func_type>()
devuelvenullptr
, la siguiente mejor referencia al objetivo almacenado sería utilizar una función o functor envoltorio que llame a la función almacenada y almacene la información necesaria. Esta función o functor envoltorio se puede llamar en lugar de lastd::function
original y puede almacenar información como el nombre o la dirección de la función en memoria, para su uso en la depuración más adelante.En cuanto a la adquisición del objetivo mediante técnicas de magia de plantillas, una posible solución es utilizar técnicas de borrado de tipos como
std::any
oboost::any
para almacenar el objetivo en un contenedor de tipo borrado. Esto permitiría capturar lambdas y funciones puras de C dentro del mismo contenedor, mientras se retienen la semántica y la usabilidad destd::function
dentro del código de la biblioteca. Sin embargo, este enfoque vendría con cierta sobrecarga de rendimiento debido a la necesidad de comprobaciones y conversiones de tipo dinámico.