2011-02-13 19 views
5

Así que estoy trabajando en un formato de archivo para almacenar datos estructurados definidos en algún tipo de rango. El ejemplo más simple sería algo así como valores flotantes en el tiempo, pero lo estoy diseñando para permitir múltiples dimensiones y datos arbitrarios en cada punto. También me gustaría almacenar la estructura de los datos en el encabezado del archivo porque permitirá algunas características interesantes.¿Definición de estructura de introspección en C++?

Al principio pensé que tendría al usuario construir su estructura de datos utilizando una jerarquía de clases, por lo que podría hacer algo como esto:

pf_type data = record(PF_DOUBLE) (
        record("position")(
        field("xp") & 
        field("yp") & 
        field("zp")) & 
        record("velocity")(
        field("xv") & 
        field("yv") & 
        field("zv")) & 
        record("acceleration")(
        field("xa") & 
        field("ya") & 
        field("za"))); 

lo que equivaldría a algo como esto en C :

struct { 
    struct position { 
     double xp,yp,zp; 
    } 
    struct velocity { 
     double xv,yv,zv; 
    } 
    struct acceleration { 
     double xa,ya,za; 
    } 
} 

no es terrible, pero aún requiere que el usuario defina por separado ac estructura de utilizar realmente al leer/escribir los datos.

Pensé que sería genial si solo pudieran definir una estructura común que pasaron a mi biblioteca y la introspeché para obtener la información para escribir en el archivo. Aunque no tengo idea si algo así es remotamente posible en C++. Mi pensamiento es que podría estar usando alguna plantilla de metaprogramación mágica pero que sería extremadamente desordenado. Así que pensé en solicitar algunas ideas de aquellos que saben más sobre C++ que yo.

+2

que está creando esencialmente un DSL y no hay que reconocer el esfuerzo que conlleva. – wheaties

+2

Estoy de acuerdo con wheaties, pero permítanme formularlo de manera más positiva: lo que están haciendo es una buena idea, es decir, es un diseño de sonido, y no dejen que lo disudemos de él. Pero estás solo aquí, C++ casi no ofrece ayuda para este tipo de trabajo. –

+0

Eso es lo que estaba pensando, pensé que básicamente tendría que escribir un analizador de estructuras usando plantillas, ick. –

Respuesta

7

No exactamente lo que está buscando, pero probablemente una muy buena fuente de inspiración, sería Google's Protobufs. Toman un enfoque ligeramente diferente de los que discutiste en tu pregunta. Con protobuf, primero describa sus estructuras de datos en archivos .proto, y luego el código repetitivo codecs de compip de protobuf (protoc) para uno de varios lenguajes diferentes, incluyendo C++.

El código codegened es totalmente capaz de reflejar sobre las estructuras que se definieron en el archivo .proto, y para qué se optimiza más el protocolo para la serialización de datos binarios para ser enviados a través del cable. Obviamente, pagarás un poco de un golpe de rendimiento, pero te dará una reflexión de muy alta calidad, y el golpe de penetración para accesos simples no es tan alto.

Esencialmente, los clientes de su biblioteca podrían pasarle un protobuf relleno. Ya sea llamándote directamente, o a través de una llamada de red.

+0

Esa puede ser la forma en que termino yendo, realmente quería mantener todo lo que yo pensaba ... –

3

La maquinaria de la plantilla es demasiado primitiva para poder hacer este tipo de cosas razonablemente. Una mejor opción en mi opinión es tener un archivo separado fácil de editar y fácil de analizar que describa la estructura de datos y luego a partir de esa definición generar el código C++ que necesita.

Escribir generadores de código en C++ es sin embargo molesto porque C++ I/O, análisis, formateo y manipulación de cadenas es subóptimo, mi sugerencia es usar Python u otro very high level language para esa parte.

Todo se puede poner probablemente en un archivo Makefile con las dependencias adecuadas (es decir, si el archivo de descripción cambia los archivos C++ regenerativos) y la compilación sigue siendo automática.

Tener un archivo C++ "normal" en lugar de trucos de plantilla va a hacer su vida mucho más fácil (tiempo de compilación, mensajes de error, incompatibilidades de compiladores para plantillas hard-core, soporte para depuración del código generado).

+0

Estoy completamente de acuerdo ... hasta el argumento innecesario y el fanatismo en el último párrafo. Quítelo para una respuesta mucho mejor, pero, también, esto está cerca de la respuesta de sblom, excepto en términos generales en lugar de describir protobufs. –

+2

@Fred Nurk: Ok ... admití haber reaccionado exageradamente. Pero es sorprendente la cantidad de daño que un enfoque tan imperturbable como único utilizó IMO para la comunidad de C++. Muchos programadores de C++ se golpean la cabeza contra las paredes para poder resolver problemas sin problemas utilizando herramientas deficientes. – 6502

+0

Muchos programadores se bloquean en un solo idioma y se pierden las ventajas de la generación de código, etc., en lugar de crear una caja de herramientas propia y combinar varias herramientas. Esto se ve agravado por los IDE que requieren que siga las ideas de sus diseñadores sobre cómo debe trabajar en lugar de combinar herramientas más simples (como make, aunque tiene limitaciones severas, pero también existen otros sistemas de compilación) que se ajustan a * su * proyecto. En la misma línea, también me encanta Python, pero otras herramientas pueden llenar ese vacío. –

0

Boost.Fusion tiene algunos trucos aseados para llevar la reflexión en tiempo de compilación a C++, en tu caso, estarás más interesado en BOOST_FUSION_ADAPT_STRUCT, creo.

Si desea agregar una sobrecarga adicional, para poder obtener campos de cadenas, por ejemplo. Necesitarás agregar algunas habilidades complementarias.

La cosa entera se puede hacer con macros y plantillas ... pero prefiero seguir con protobuf;)

Cuestiones relacionadas