2009-10-23 9 views
6

LLVM tiene su propia alternativa enrollada a mano a RTTI que es una mejora de velocidad sobre RTTI incorporado y permite fundición dinámica a clases sin vtable (dyn_cast). Sin embargo, todavía se puede usar de la misma manera que se usa dynamic_cast<> aunque permite que se use con más clases.¿LLVM es una excepción a la regla para evitar conversiones dinámicas?

dyn_cast<> template documentation

LLVM es un proyecto de buena reputación C++ por lo que esto parece ir en contra de lo común decir que demasiados moldes dinámica es un signo de un mal diseño, también conocido como un olor código. Sin duda, un elenco dinámico de mejor rendimiento no hace nada para mejorar su uso en el diseño que un estándar dynamic_cast. Entonces, ¿quién está aquí? ¿Hay casos en los que el uso a gran escala de fundición dinámica sea una buena opción de diseño en el código C++? Google presenta 690 ocurrencias de este tipo de conversión dinámica en el código fuente de troncales LLVM.

Uses of dyn_cast<> in LLVM trunk

+0

Creo que simplemente muestra que "a veces, en un gran proyecto de software, tiene que doblar algunas de las reglas". O tal vez "los compiladores, o los marcos relacionados con el compilador, tienen que meterse con trucos de bajo nivel que generalmente son una mala idea". Eso no significa que podamos concluir algo sobre el uso de 'dynamic_cast' * en general * – jalf

+0

Esto parece ignorar completamente 'las reglas'. Yo no llamaría 690 ocurrencias doblando las reglas.No veo nada especial acerca de compiladores o marcos relacionados con compiladores que signifiquen que se les permita romper creencias de diseño. La conversión dinámica aquí no tiene ningún efecto en el código de salida o en el código de entrada del compilador, simplemente es parte del diseño. Podría continuar con su argumento para decir que cualquier software suficientemente grande o complejo puede incumplir las reglas de diseño, lo que cuestiona seriamente este tipo de consejos de diseño para evitar 'dynamic_cast'. –

Respuesta

7

Si bien los golpes de rendimiento son una razón para evitar dynamic_cast<> para jerarquías de clases grandes, no es la única razón por la que puede querer evitarlos. Mejor rendimiento o no, no se debe alentar más a usar dyn_cast<> debido a este reclamo.

Por otro lado, no hay nada de malo en usar dynamic_cast<> cuando es la mejor herramienta para el trabajo. Si su uso está justificado y es la forma más limpia de resolver un problema, siempre es correcto, independientemente del "dicho común".

No me alejaría de los proyectos populares simplemente porque usan dynamic_cast<> s, goto o cualquier otro idioma que haya caído en desgracia.

+0

Absolutamente, creo que es un gran proyecto, ¿eso significa que deberíamos tener en cuenta menos los consejos para evitar el 'dynamic_cast <>'? –

+0

no, debe tener en cuenta los consejos cuando los está usando y pensar: "¿es esta la mejor manera de hacerlo?" –

1

creo que la dinámica de los moldes son malas no porque son lentos, pero debido a que implica que su código es demasiado estrechamente unida.

+0

Aunque son muy lentos también. Cerca de 1 microsec por segundo para nosotros. – Crashworks

+0

@Crashworks - ¿Qué tan profunda es la jerarquía de herencia? Creo que la implementación de GCC de 'dynamic_cast' es O (n) en la profundidad, lo que puede ser muy malo para algunos sistemas. – Tom

+0

Creo que se trata de 6-8 niveles en el caso que probé. Hay literalmente miles de clases en toda la aplicación. – Crashworks

-1

Solo he echado un vistazo muy rápido a la implementación de dyn_cast e isa en la documentación de LLVM.

El exmaple en el código tiene el siguiente:

struct bar { 
    bar() {} 
private: 
    bar(const bar &); 

}; 
struct foo { 
    void ext() const; 
    /* static bool classof(const bar *X) { 
    cerr << "Classof: " << X << "\n"; 
    return true; 
    }*/ 
}; 

template <> inline bool isa_impl<foo,bar>(const bar &Val) { 
    errs() << "Classof: " << &Val << "\n"; 
    return true; 
} 

La prueba se llama con un B y tiene:

if (!isa<foo>(B1)) return; 
if (!isa<foo>(B2)) return; 

si entiendo lo que está pasando correctamente, la plantilla isa (que es utilizado por dyn_cast) utiliza la especialización explícita de isa_impl para vincular la barra con foo. ¡En los ejemplos dados, parece que isa<foo>(B1) es verdadero!

De todos modos, este comportamiento es muy diferente al de dynamic_cast, así que realmente no creo que puedas compararlos entre sí.

Obviamente, puedo estar entendiendo mal lo que LLVM está haciendo, así que por favor avíseme si no he entendido el código.

+0

Directamente de la documentación: El operador dyn_cast <> es una operación de "comprobación de colada". Comprueba si el operando es del tipo especificado y, si es así, le devuelve un puntero (este operador no funciona con las referencias). Si el operando no es del tipo correcto, se devuelve un puntero nulo. Por lo tanto, esto funciona de manera muy similar al operador dynamic_cast <> en C++, y debe usarse en las mismas circunstancias. Así que no veo por qué no puede comparar dynamic_cast contra dyn_cast. En su ejemplo, no veo de dónde vienen B1 y B2. –

+0

El código anterior proviene de un enlace fuera de la página a la que se hace referencia en la pregunta. Este es su código (es decir, LLVM). Aquí está el enlace directo: http://llvm.org/doxygen/Casting_8h-source.html. B1 y B2 provienen de un ejemplo en esa página más abajo. Acabo de cortar y pegar el código de su encabezado. Por cierto, nada de lo que has pegado aquí realmente dice cómo se produce el reparto dinámico. Simplemente dice que es un "cast de verificación" similar a dynamic_cast. –

+1

No creo que la implementación realmente afecte la pregunta que estoy haciendo aquí. La cita clave de la documentación literal es: 'Por lo tanto, esto funciona muy parecido al operador dynamic_cast <> en C++, y debe utilizarse en las mismas circunstancias'. –

Cuestiones relacionadas