librerias - programa c++
Bibliotecas de atributos y reflexiones para C++ (8)
La mayoría de los proyectos de C ++ maduros parecen tener un sistema propio de reflexión y atributos , es decir, para definir atributos a los que se puede acceder por cadena y que se pueden serializar automáticamente. Al menos muchos proyectos de C ++ en los que participé parecían reinventar la rueda .
¿Conoces alguna buena biblioteca de código abierto para C ++ que admita contenedores de reflexión y de atributos, específicamente:
- Definición de RTTI y atributos a través de macros
- Accediendo a RTTI y atributos por código
- Serialización automática de atributos
- Escuchando modificaciones de atributos (por ejemplo, OnValueChanged)
No es general, pero QT lo admite a través de un metacompilador, y es GPL. Mi comprensión de hablar con la gente de QT fue que esto no es posible con C ++ puro, de ahí la necesidad del moc.
Podrías echar un vistazo a las dos herramientas a continuación. Nunca he usado ninguno de ellos, así que no puedo decirles lo (practicamente) que son.
XRTTI :
Xrtti es una herramienta y biblioteca de C ++ que lo acompaña, que amplía el sistema de tipo de tiempo de ejecución estándar de C ++ para proporcionar un conjunto mucho más rico de información de reflexión sobre clases y métodos para manipular estas clases y sus miembros.
OpenC ++ :
OpenC ++ es una biblioteca de frontend C ++ (lexer + parser + DOM / MOP) y un traductor de fuente a fuente. OpenC ++ permite el desarrollo de herramientas de lenguaje C ++, extensiones, optimizaciones de compilador específicas de dominio y protocolos de metaobjetos en tiempo de ejecución.
Miré estas cosas por bastante tiempo, pero tienden a ser muy duros. Pueden evitar que use herencia, o tener constructores extraños, etc. Al final terminaron siendo una carga demasiado pesada en lugar de una conveniencia.
Este enfoque para exponer miembros que ahora uso es bastante liviano y te permite explorar una clase para la serialización o configurar todos los campos llamados "x" a 0, por ejemplo. También está estáticamente determinado, por lo que es muy, muy rápido. No hay capas de código de biblioteca o gen de código que preocuparse por jugar con el proceso de compilación. Se generaliza a jerarquías de tipos anidados.
Configura tu editor con algunas macros para automatizar la escritura de algunas de estas cosas.
struct point
{
int x;
int y;
// add this to your classes
template <typename Visitor>
void visit(Visitor v)
{
v->visit(x, "x");
v->visit(y, "y");
}
};
/** Outputs any type to standard output in key=value format */
struct stdout_visitor
{
template <typename T>
void visit(const T& rhs)
{
rhs.visit(this);
}
template <typename Scalar>
void visit (const Scalar& s, const char* name)
{
std::cout << name << " = " << s << " ";
}
}
Esto es lo que obtienes cuando C ++ se encuentra con Reflection:
Lo que elija, probablemente tenga macros horribles, código difícil de depurar o pasos de compilación raros. He visto que un sistema genera automáticamente el código de serialización del archivo PDB de DevStudio.
En serio, para proyectos pequeños, será más fácil escribir funciones de guardar / cargar (o usar operadores de transmisión). De hecho, eso también puede ser válido para grandes proyectos: es obvio lo que está sucediendo y, por lo general, es necesario cambiar el código si la estructura cambia.
Kit de herramientas de introspección / reflexión automática. Use un compilador de metadatos como Qt y agregue metainformación directamente a los archivos de objeto. Intuitivo, fácil de usar. Sin dependencias externas. Incluso permite automáticamente reflejar std :: string y luego usarlo en scripts. Por favor visite IDK
Esta es una debilidad notoria del lenguaje C ++ en general porque las cosas que tendrían que ser estandarizadas para hacer que las implementaciones de reflexión sean portátiles y valiosas no son estándar. Las convenciones de llamadas, los diseños de objetos y el cambio de símbolo vienen a la mente, pero también hay otros.
La falta de dirección del estándar significa que los implementadores de compiladores harán algunas cosas de manera diferente, lo que significa que muy pocas personas tienen la motivación de escribir una biblioteca de reflexión portátil, lo que significa que las personas que necesitan reflexión reinventan la rueda, pero solo lo suficiente para lo que necesitan. Esto sucede ad infinitum , y aquí estamos.
Hay un nuevo proyecto que proporciona reflexión en C ++ utilizando un enfoque totalmente diferente: CAMP . https://github.com/tegesoft/camp
CAMP no utiliza un precompilador, las clases / propiedades / funciones / ... se declaran manualmente usando una sintaxis similar a boost.python o luabind. Por supuesto, las personas pueden usar un precompilador como gccxml o open-c ++ para generar esta declaración si así lo prefieren.
Se basa únicamente en encabezados C ++ y boost, y gracias al poder de la metaprogramación de plantillas, admite todo tipo de entidad vinculable (herencia y constructores extraños no son un problema, por ejemplo).
Se distribuye bajo la licencia MIT (anteriormente LGPL).
Miré esto por un tiempo también. La solución más fácil actual parece ser BOOST_FUSION_ADAPT_STRUCT . Prácticamente, una vez que tiene una biblioteca / encabezado, solo necesita agregar sus campos de estructura en la macro BOOST_FUSION_ADAPT_STRUCT (), como se muestra en el último segmento del código . Sí, tiene restricciones que muchas otras personas han mencionado. Y no admite oyentes directamente.
Las otras soluciones prometedoras que investigué son
- CAMP y XRTTI / gccxml, sin embargo, ambos parecen ser un obstáculo para llevar la dependencia de herramientas externas a su proyecto.
- Hace años utilicé Perl
c2ph
/pstruct
para volcar la metainformación de la salida degcc -gstabs
, que es menos intrusiva pero necesita más trabajo aunque funcionó perfectamente para mí.
Con respecto al enfoque boost / __ cxa, una vez que sepas todos los detalles pequeños, agregar / cambiar estructuras o campos es fácil de mantener. actualmente lo usamos para construir una capa de enlace de tipos personalizados encima de dbus, serializar la API y ocultar los detalles de transporte / RPC para un subsistema de servicio de objetos gestionados.