2009-10-06 14 views
18

Conozco los siguientes enfoques para delegados C++:Delegados Fast C++

. Interfaces con funciones virtuales puras
. Boost.Function
. The Fastest Possible C++ Delegates
. The Impossibly Fast C++ Delegates
. Fast C++ Delegates
. Fast C++ Delegate: Boost.Function 'drop-in' replacement and multicast

Cada uno tiene sus pros y sus contras. Algunos son más rápidos, otros son más flexibles, otros son más ricos en características, algunos son más compatibles con el estándar y otros son más portátiles, pero personalmente me gusta mucho el tercero: los Delegados Imposibly Fast C++ de Sergey Riazanov. El problema, sin embargo, es que sus delegados no son comparables:

Mis delegados no se pueden comparar. Los operadores de comparación no están definidos porque un delegado no contiene un puntero al método. El puntero a una función de stub puede ser diferente en varias unidades de compilación.

A lo que los lectores han respondido:

"puntero a una función de código auxiliar puede ser diferente en diferentes unidades de compilación". AFAIK, esto no es verdad. Se requiere que los compiladores reutilicen las funciones de las plantillas generadas en diferentes unidades de compilación (de esto estoy seguro, pero creo que Borland una vez violó esta regla). Creo que es porque las clases (que no están en espacios de nombres 'sin nombre') usan enlaces externos y la forma en que usas las funciones de stub siempre evitará que estén en línea (aunque esto tampoco debería ser un problema como tomar la dirección de la función forzará que se genere una versión no en línea y el 'vinculador externo' realizado por el enlazador eliminará todas las funciones llamadas con el mismo nombre (se supone y se requiere que sean idénticas por el estándar)) ...

Si define una función de plantilla, una unidad de traducción (archivo cpp) y luego define la misma función de manera diferente en otra unidad de traducción, solo una de las dos versiones la convertirá en el ejecutable final. (Esto en realidad infringe la "Regla de una sola definición", pero funciona en GCC, al menos ... no estoy seguro acerca de MSVC). El punto es: la dirección [del apéndice] será la misma en unidades diferentes.

Lo instaría a que actualice el artículo (incluida la capacidad de comparación) si encuentra que esto es cierto para MSVC, si MSVC es la concesión de normas, en este sentido.

Ahora el artículo tiene cuatro años y el autor no ha respondido a ninguno de los comentarios durante los últimos tres años, así que me pregunto si hay algún mérito en el comentario anterior y si este específico la implementación puede ser modificada para apoyar las comparaciones. ¿El estándar de C++ prohíbe específicamente tal uso? De ser así, ¿alguno de los compiladores recientes realmente cumple con los estándares en ese sentido?

Gracias.

+1

Incluso si la declaración era cierta, la compaibilidad se puede agregar fácilmente agregando un miembro que de otra forma no se usará a sus delegados. – MSalters

Respuesta

11

El código es a la vez estándar y fino. No veo ningún lugar donde viole la ODR, y es cierto que todas las instancias de una plantilla de función con los mismos parámetros de plantilla deben tener "la misma dirección" (en el sentido de que todos los punteros a las funciones deberían ser iguales): cómo esto se logra no es importante. ISO C++ 03 14.5.5.1 [temp.over.link] describe las reglas con más detalle.

Por lo tanto, una comparación bien podría definirse allí de una manera conforme y portátil.

+0

¿Qué sucede si las instancias de plantilla residen en diferentes DLL? ¿O uno en la aplicación principal y otros en diferentes DLL? – user1095108

+0

El estándar realmente no trata con la noción de DLL/bibliotecas compartidas. En la práctica, por supuesto, dado que se compilan y vinculan por separado, no hay forma de que los compiladores combinen instancias. Entonces, sí, eso sería una mierda. –