2011-02-13 25 views
5

Quindi sto lavorando su un formato di file per la memorizzazione di dati strutturati definiti su un certo tipo di intervallo. L'esempio più semplice sarebbe qualcosa di simile ai valori float nel tempo, ma lo sto progettando per consentire più dimensioni e dati arbitrari in ogni punto. Mi piacerebbe anche archiviare la struttura dei dati nell'intestazione del file, in quanto consentirà alcune caratteristiche chiare.Definizione struct introspettiva in C++?

un primo momento ho pensato che avrei avuto l'utente a costruire la loro struttura dei dati utilizzando una gerarchia di classi, così si potrebbe fare qualcosa di simile:

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"))); 

che sarebbe equivalente a qualcosa di simile a C :

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

non è terribile, ma richiede comunque all'utente di definire separatamente ac struct utilizzare effettivamente durante la lettura/scrittura dei dati.

Ho pensato che sarebbe stato bello se avessero potuto definire una normale c-struct passata alla mia libreria e l'ho introspezionata per ottenere le informazioni da scrivere nel file. Anche se non ho idea se qualcosa del genere sia remotamente possibile in C++. Il mio pensiero è che potrebbe usare qualche modello di metaprogrammazione della magia, ma sarebbe estremamente disordinato. Quindi ho pensato di sollecitare alcune idee da quelli che conoscono meglio di me il C++.

+2

sei essenzialmente la creazione di un DSL e non c'è niente da fare intorno lo sforzo che comporta. – wheaties

+2

Sono d'accordo con i bianchi, ma lascia che io lo formuli in modo più positivo: quello che stai facendo è una buona idea, cioè un sound design, e non lasciarci dissuadere da esso. Ma sei qui da solo, il C++ non offre quasi alcun aiuto per questo tipo di lavoro. –

+0

Questo è quello che stavo pensando, ho pensato che avrei dovuto scrivere un parser di struct usando template, ick. –

risposta

7

Non esattamente quello che stai cercando, ma probabilmente una fonte molto buona per l'ispirazione, sarebbe Google's Protobufs. Hanno un approccio leggermente diverso da quelli che hai discusso nella tua domanda. Con protobuf, per prima cosa descrivi le tue strutture di dati nei file .proto, e poi il codice dello scriptplot di protobuf compiler (protoc) codegens per una delle diverse lingue, incluso C++.

Il codice codegened è pienamente in grado di riflettere sulle strutture definite nel file .proto e quale protobuf è ottimizzato per la serializzazione di dati binari per essere inviati via cavo. Ovviamente, pagherai un piccolo colpo sulle prestazioni, ma otterrai riflessi di alta qualità e il successo perfetto per accessi semplici non è poi così alto.

In sostanza, i clienti della tua biblioteca potrebbero inviarti un protobuf compilato. O chiamandoti direttamente o tramite una chiamata di rete.

+0

Questo potrebbe essere il modo in cui finisco, volevo davvero mantenere tutto ciò che era contenuto ... –

3

I modelli di macchinari sono troppo primitivi per poter fare questo genere di cose in modo ragionevole. Un'opzione migliore a mio parere è di avere un file separato facile da modificare e facile da analizzare che descriva la struttura dei dati e quindi da quella definizione generi il codice C++ che ti serve.

La scrittura di generatori di codice in C++ è comunque fastidiosa perché l'I/O C++, l'analisi, la formattazione e la manipolazione delle stringhe sono subottimali, il mio suggerimento è di usare Python o un altro very high level language per quella parte.

Tutto può quindi essere inserito in un Makefile con dipendenze appropriate (ad esempio se il file di descrizione cambia rigenerare i file C++) e quindi la build è ancora automatica.

Avere un file C++ "normale" al posto del trucchetto renderà la tua vita molto più semplice (tempo di compilazione, messaggi di errore, incompatibilità con i compilatori per i modelli di hard-core, supporto per il debug del codice generato).

+0

Sono completamente d'accordo ... fino all'argomentazione inutile e al fanatismo nell'ultimo paragrafo. Rimuovilo per una risposta molto migliore, ma, anche, questo è vicino alla risposta di sblom, tranne in termini generali invece di descrivere protobufs. –

+2

@Fred Nurk: Ok ... ho ragionevolmente esagerato. Ma è incredibile la quantità di danni che un tale imago si avvicina a quelli che IMO ha fatto alla comunità C++. Molti programmatori C++ stanno sbattendo la testa contro i muri per essere in grado di risolvere problemi senza problemi usando strumenti scadenti. – 6502

+0

Molti programmatori si bloccano in una singola lingua e perdono i vantaggi della generazione di codice, ecc. Piuttosto che creare una propria casella degli strumenti e combinare più strumenti. Ciò è esacerbato dagli IDE che richiedono di seguire le idee dei loro progettisti su come dovresti lavorare piuttosto che combinare strumenti più semplici (come make, anche se presenta gravi limitazioni, ma esistono anche altri sistemi di costruzione) che si adattano al tuo progetto *. Allo stesso modo, amo anche Python, ma altri strumenti possono colmare questa lacuna. –

0

Boost.Fusion ha alcuni trucchetti per portare la riflessione in compilazione in C++, nel tuo caso, ti interesserà soprattutto BOOST_FUSION_ADAPT_STRUCT.

Se si desidera aggiungere un sovraccarico supplementare, per poter ad esempio ottenere i campi da stringhe. Dovrai aggiungere alcune abilità complementari.

Il tutto può essere fatto con le macro e modelli ... ma io preferisco bastone con protobuf;)