Las cargas de bibliotecas C++, el estándar incluido, le permiten adaptar sus objetos para su uso en las bibliotecas. La elección suele ser entre una función miembro o una función libre en el mismo espacio de nombres.La mecánica de la extensión a través de funciones gratuitas o funciones miembro
Me gustaría saber qué mecanismos y construcciones utiliza el código de la biblioteca para enviar una llamada que invocará una de estas funciones de "extensión", sé que esta decisión debe tomar lugar durante el tiempo de compilación e implica plantillas. El siguiente psuedocode en tiempo de ejecución no es posible/sin sentido, los motivos están fuera del alcance de esta pregunta.
if Class A has member function with signature FunctionSignature
choose &A.functionSignature(...)
else if NamespaceOfClassA has free function freeFunctionSignature
choose freeFunctionSignature(...)
else
throw "no valid extension function was provided"
El código anterior parece el código de tiempo de ejecución: /. Entonces, ¿cómo averigua la biblioteca el espacio de nombres en el que se encuentra una clase, cómo detecta las tres condiciones, qué otras trampas hay que evitar?
La motivación de mi pregunta es que pueda encontrar los bloques de distribución en las bibliotecas y poder usar los constructos en mi propio código. Por lo tanto, las respuestas detalladas ayudarán.
!! TO WIN BOUNTY !!
Ok, según la respuesta de Steve (y los comentarios) ADL y SFINAE son los constructos clave para cablear el envío en tiempo de compilación. Tengo mi cabeza alrededor de ADL (primitivamente) y SFINAE (otra vez rudemental). Pero no sé cómo se entrenan juntos de la manera que creo que deberían.
Quiero ver un ejemplo ilustrativo de cómo estas dos construcciones se pueden juntar para que una biblioteca pueda elegir en tiempo de compilación si llamar a una función miembro proporcionada por el usuario en un objeto, o una función gratuita suministrada por el usuario en el espacio de nombres del mismo objeto. Esto solo debe hacerse utilizando las dos construcciones anteriores, sin despacho en tiempo de ejecución de ningún tipo.
Digamos que el objeto en cuestión se llama NS::Car
, y este objeto debe proporcionar el comportamiento de MoveForward(int units)
, como una función miembro de c. Si el comportamiento se recogerá del espacio de nombres del objeto, probablemente se verá como MoveForward(const Car & car_, int units)
. Vamos a definir la función que desea enviar mover(NS::direction d, const NS::vehicle & v_)
, donde la dirección es una enumeración, y v_ es una clase base de NS::car
.
No puede anular 'operator <<' en su clase para dar salida a una secuencia. Un operador miembro debe tener la clase a la izquierda del operador, no a la derecha. Además, la búsqueda de nombre es parte del compilador, no de la biblioteca, e involucrará plantillas solo si hay una clase de plantilla o función de plantilla involucrada. Si está preguntando cómo se realiza la búsqueda de nombres, aclare su pregunta. De lo contrario, no sé lo que estás preguntando. –
@david Sí, me equivoqué con 'operator <<' Eliminé el ejemplo, pero alguien estaba editando mi pregunta y sobrescribió la eliminación: D –