Perché il C ++ non ha riflessione?


337

Questa è una domanda alquanto bizzarra. I miei obiettivi sono comprendere la decisione di progettazione del linguaggio e identificare le possibilità di riflessione in C ++.

  1. Perché il comitato linguistico C ++ non è andato verso l'implementazione della riflessione sul linguaggio? La riflessione è troppo difficile in un linguaggio che non gira su una macchina virtuale (come java)?

  2. Se si dovesse implementare la riflessione per il C ++, quali saranno le sfide?

Immagino che gli usi della riflessione siano ben noti: gli editor possono essere scritti più facilmente, il codice del programma sarà più piccolo, le simulazioni possono essere generate per i test unitari e così via. Sarebbe bello se potessi commentare anche gli usi della riflessione.

Risposte:


631

Esistono diversi problemi con la riflessione in C ++.

  • È un sacco di lavoro da aggiungere e il comitato C ++ è abbastanza conservatore e non dedica tempo a nuove funzionalità radicali a meno che non siano sicuri che ripagherà. (È stato formulato un suggerimento per l'aggiunta di un sistema di moduli simile agli assembly .NET, e anche se penso che ci sia consenso generale sul fatto che sarebbe bello avere, al momento non è la loro massima priorità, ed è stato respinto fino a dopo C ++ 0x. La motivazione di questa funzione è quella di sbarazzarsi del #includesistema, ma consentirebbe anche almeno alcuni metadati).

  • Non paghi per ciò che non usi. Questa è una delle filosofie di base del design alla base del C ++. Perché il mio codice dovrebbe contenere metadati se non potrei mai averne bisogno? Inoltre, l'aggiunta di metadati potrebbe inibire l'ottimizzazione del compilatore. Perché dovrei pagare quel costo nel mio codice se non potrei mai aver bisogno di quei metadati?

  • Il che ci porta a un altro punto di grande: C ++ rende molto poche garanzie circa il codice compilato. Al compilatore è consentito fare praticamente qualsiasi cosa gli piaccia, purché la funzionalità risultante sia quella che ci si aspetta. Ad esempio, non è necessario che le tue classi siano effettivamente presenti . Il compilatore può ottimizzarli via, incorporare tutto ciò che fanno e spesso fa proprio questo, perché anche il semplice codice di modello tende a creare alcune istanze di modello. La libreria standard C ++ si basa su questa ottimizzazione aggressiva. I teatri sono efficaci solo se l'overhead di istanziare e distruggere l'oggetto può essere ottimizzato. operator[]su un vettore è paragonabile solo all'indicizzazione di array non elaborato in termini di prestazioni perché l'intero operatore può essere incorporato e quindi rimosso completamente dal codice compilato. C # e Java offrono molte garanzie sull'output del compilatore. Se definisco una classe in C #, tale classe esisterà nell'assembly risultante. Anche se non lo uso mai. Anche se tutte le chiamate alle sue funzioni membro potrebbero essere integrate. La classe deve essere lì, in modo che la riflessione possa trovarla. Parte di questo è alleviata dalla compilazione C # in bytecode, il che significa che il compilatore JIT può farlorimuovere le definizioni di classe e le funzioni incorporate se lo desidera, anche se il compilatore C # iniziale non può farlo. In C ++, hai un solo compilatore e deve generare un codice efficiente. Se ti fosse permesso di ispezionare i metadati di un eseguibile C ++, ti aspetteresti di vedere ogni classe definita, il che significa che il compilatore dovrebbe preservare tutte le classi definite, anche se non sono necessarie.

  • E poi ci sono modelli. I modelli in C ++ non assomigliano ai generici in altre lingue. Ogni istanza del modello crea un nuovo tipo. std::vector<int>è una classe completamente separata da std::vector<float>. Ciò si aggiunge a molti tipi diversi in un intero programma. Cosa dovrebbe vedere la nostra riflessione? Il modello std::vector ? Ma come può, dato che è un costrutto di codice sorgente, che non ha significato in fase di esecuzione? Dovrebbe vedere le classi separate std::vector<int>e std::vector<float>. E std::vector<int>::iteratore std::vector<float>::iterator, lo stesso perconst_iteratore così via. E una volta che passi alla metaprogrammazione dei modelli, finisci rapidamente per creare un'istanza di centinaia di modelli, tutti i quali vengono incorporati e rimossi nuovamente dal compilatore. Non hanno alcun significato, tranne che come parte di un metaprogramma in fase di compilazione. Tutte queste centinaia di classi dovrebbero essere visibili alla riflessione? Dovrebbero, perché altrimenti la nostra riflessione sarebbe inutile, se non garantisse nemmeno che le classi che ho definito saranno effettivamente . E un problema secondario è che la classe template non esiste fino a quando non viene istanziata. Immagina un programma che utilizza std::vector<int>. Il nostro sistema di riflessione dovrebbe essere in grado di vedere std::vector<int>::iterator? Da un lato, ti aspetteresti sicuramente di sì. È una classe importante, ed è definita in termini di std::vector<int>, che lo faesiste nei metadati. D'altra parte, se il programma non utilizza mai effettivamente questo modello di classe iteratore, il suo tipo non sarà mai stato istanziato e quindi il compilatore non avrà generato la classe in primo luogo. Ed è troppo tardi per crearlo in fase di esecuzione, poiché richiede l'accesso al codice sorgente.

  • E infine, la riflessione non è così vitale in C ++ come in C #. Il motivo è di nuovo, la metaprogrammazione del modello. Non può risolvere tutto, ma per molti casi in cui altrimenti ricorrere alla riflessione, è possibile scrivere un metaprogramma che fa la stessa cosa in fase di compilazione. boost::type_traitsè un semplice esempio. Vuoi sapere del tipo T? Controlla il suo type_traits. In C #, dovresti pescare in giro dopo il suo tipo usando il riflesso. La riflessione sarebbe comunque utile per alcune cose (l'uso principale che posso vedere, che la metaprogrammazione non può facilmente sostituire, è per il codice di serializzazione autogenerato), ma porterebbe alcuni costi significativi per C ++, e non è necessario tanto spesso quanto è in altre lingue.

Modifica: in risposta ai commenti:

cdleary: Sì, i simboli di debug fanno qualcosa di simile, in quanto memorizzano metadati sui tipi utilizzati nell'eseguibile. Ma soffrono anche dei problemi che ho descritto. Se hai mai provato a eseguire il debug di una build di rilascio, saprai cosa intendo. Esistono ampie lacune logiche in cui è stata creata una classe nel codice sorgente, che è stata incorporata nel codice finale. Se dovessi usare la riflessione per qualcosa di utile, ne avresti bisogno per essere più affidabile e coerente. Così com'è, i tipi svanirebbero e scomparirebbero quasi ogni volta che compili. Modifichi un piccolo dettaglio e il compilatore decide di cambiare quali tipi vengono incorporati e quali no, come risposta. Come si estrae qualcosa di utile da ciò, quando si ' non sei nemmeno garantito che i tipi più rilevanti saranno rappresentati nei tuoi metadati? Il tipo che stavi cercando potrebbe essere stato lì nell'ultima build, ma ora non c'è più. E domani qualcuno controllerà un piccolo cambiamento innocente in una piccola funzione innocente, che rende il tipo abbastanza grande da non essere completamente allineato, quindi tornerà di nuovo. È ancora utile per i simboli di debug, ma non molto di più. Odierei provare a generare codice di serializzazione per una classe in questi termini. ma non molto di più. Odierei provare a generare codice di serializzazione per una classe in questi termini. ma non molto di più. Odierei provare a generare codice di serializzazione per una classe in questi termini.

Evan Teran: Naturalmente questi problemi potrebbero essere risolti. Ma questo risale al mio punto n. 1. Ci vorrebbe molto lavoro e il comitato C ++ ha molte cose che ritengono più importanti. Il vantaggio di ottenere una riflessione limitata (e sarebbe limitata) in C ++ è davvero abbastanza grande da giustificare la concentrazione su questo a spese di altre funzionalità? C'è davvero un enorme vantaggio nell'aggiungere funzionalità al linguaggio principale che può già (principalmente) essere fatto attraverso librerie e preprocessori come QT? Forse, ma la necessità è molto meno urgente che se tali librerie non esistessero. Tuttavia, per i tuoi suggerimenti specifici, ritengo che non consentirli sui modelli lo renderebbe completamente inutile. Ad esempio, non potresti usare la riflessione sulla libreria standard. Che tipo di riflessione non sarebbestd::vector? I modelli sono una parte enorme del C ++. Una funzione che non funziona sui modelli è sostanzialmente inutile.

Ma hai ragione, potrebbe essere implementata una qualche forma di riflessione. Ma sarebbe un grande cambiamento nella lingua. Come è ora, i tipi sono esclusivamente un costrutto in fase di compilazione. Esistono a beneficio del compilatore e nient'altro. Una volta compilato il codice, non ci sono classi. Se ti allunghi, potresti sostenere che le funzioni esistono ancora, ma in realtà, tutto ciò che c'è è un mucchio di istruzioni per l'assemblaggio dei salti e un sacco di stack / pop di stack. Non c'è molto da fare quando si aggiungono tali metadati.

Ma come ho detto, esiste una proposta di modifica del modello di compilazione, aggiunta di moduli autonomi, memorizzazione di metadati per tipi selezionati, consentendo ad altri moduli di fare riferimento a loro senza dover fare confusione con #includes. È un buon inizio, e ad essere sincero, sono sorpreso che il comitato standard non abbia semplicemente lanciato la proposta per essere un cambiamento troppo grande. Quindi forse tra 5-10 anni? :)


2
La maggior parte di questi problemi non deve già essere risolta dai simboli di debug? Non che sarebbe performante (a causa dell'inline e dell'ottimizzazione che hai citato), ma potresti consentire la possibilità di riflessione facendo qualunque cosa facciano i simboli di debug.
cdleary,

2
Un'altra cosa sul tuo primo punto: per quanto ne so nessuno ha provato ad aggiungere la riflessione a un'implementazione C ++. Non c'è una buona esperienza con esso. Il Comitato probabilmente sarà riluttante a prendere il comando, in particolare dopo exporte vector<bool>.
David Thornley,

18
Concordo sul fatto che C ++ non avrebbe dovuto riflettere sul tempo di esecuzione. Ma la riflessione del tempo di compilazione presenta alcuni dei problemi di cui sopra e, se lo desidera, potrebbe essere utilizzata da qualcuno per creare la riflessione del tempo di esecuzione su classi particolari. Essere in grado di accedere al tipo, al nome e alle caratteristiche dell'ennesimo metodo e dell'ennesimo genitore di una classe tramite un modello? E ottenere il numero di tali al momento della compilazione? Renderebbe possibile la riflessione automatica basata su CRTP, mentre nessuno paga per ciò che non utilizza.
Yakk - Adam Nevraumont,

15
Il tuo terzo punto è per molti aspetti il ​​più importante: C ++ è pensato per essere adatto per scrivere codice autonomo su piattaforme dove la memoria costa denaro; se l'eliminazione di un codice inutilizzato consentirebbe a un programma di inserirsi in un microcontrollore che costa $ 2,00, anziché uno che costa $ 2,50, e se il codice va in 1.000.000 di unità, l'eliminazione di quel codice può far risparmiare $ 500.000. Senza riflessione, l'analisi statica può spesso identificare il 90% + di codice non raggiungibile; se è consentito Reflection, tutto ciò che può essere raggiunto tramite Reflection deve essere considerato raggiungibile, anche se il 90% non lo è.
supercat

2
c'è sicuramente qualcosa che può essere facilmente migliorato dal comitato, è finalmente dire nero su bianco che typeinfola name()funzione DEVE restituire il nome che è stato digitato dal programmatore e non qualcosa di indefinito. E dacci un stringificatore anche per gli enumeratori. Questo è in realtà cruciale per la serializzazione / deserializzazione, per aiutare a creare fabbriche ecc.
v

38

Reflection richiede che alcuni metadati sui tipi siano archiviati da qualche parte che possano essere interrogati. Poiché il C ++ si compila in codice macchina nativo e subisce pesanti modifiche a causa dell'ottimizzazione, la vista di alto livello dell'applicazione è praticamente persa nel processo di compilazione, di conseguenza, non sarà possibile interrogarli in fase di esecuzione. Java e .NET utilizzano una rappresentazione di livello molto elevato nel codice binario per macchine virtuali che rende possibile questo livello di riflessione. In alcune implementazioni C ++, tuttavia, esiste qualcosa chiamato Run Time Type Information (RTTI) che può essere considerato una versione ridotta della riflessione.


15
RTTI è nello standard C ++.
Daniel Earwicker,

1
Ma non tutte le implementazioni C ++ sono standard. Ho visto implementazioni che non supportano RTTI.
Mehrdad Afshari,

3
E la maggior parte delle implementazioni che supportano RTTI supporta anche la disattivazione tramite le opzioni del compilatore.
Michael Kohne,

21

Tutte le lingue non dovrebbero cercare di incorporare tutte le funzionalità di ogni altra lingua.

Il C ++ è essenzialmente un assemblatore di macro molto, molto sofisticato. NON è (in senso tradizionale) un linguaggio di alto livello come C #, Java, Objective-C, Smalltalk, ecc.

È utile disporre di strumenti diversi per diversi lavori. Se abbiamo solo dei martelli, tutto sembrerà un chiodo, ecc. Avere linguaggi di script è utile per alcuni lavori e linguaggi OO riflessivi (Java, Obj-C, C #) sono utili per un'altra classe di lavori, e super linguaggi vicini alla macchina a basso consumo efficienti sono utili per l'ennesima classe di lavori (C ++, C, Assembler).

Il C ++ fa un lavoro straordinario estendendo la tecnologia dell'Assemblatore a livelli incredibili di gestione della complessità e astrazioni per rendere la programmazione di compiti più grandi e complessi molto più possibili per gli esseri umani. Ma non è necessariamente un linguaggio che è il più adatto per coloro che stanno affrontando il loro problema da una prospettiva strettamente di alto livello (Lisp, Smalltalk, Java, C #). Se hai bisogno di una lingua con queste funzionalità per implementare al meglio una soluzione ai tuoi problemi, allora ringrazia quelli che hanno creato tali lingue da usare per tutti noi!

Ma C ++ è per coloro che, per qualsiasi motivo, devono avere una forte correlazione tra il loro codice e il funzionamento della macchina sottostante. Che si tratti di efficienza, di driver di dispositivo di programmazione o di interazione con i servizi del sistema operativo di livello inferiore, o qualsiasi altra cosa, C ++ è più adatto a tali compiti.

C #, Java, Objective-C richiedono tutti un sistema di runtime molto più grande e ricco per supportare la loro esecuzione. Tale runtime deve essere consegnato al sistema in questione, preinstallato per supportare il funzionamento del software. E quel livello deve essere mantenuto per vari sistemi target, personalizzato da QUALCHE ALTRO LINGUA per farlo funzionare su quella piattaforma. E quel livello intermedio - quello strato adattivo tra il sistema operativo host e il tuo codice - il runtime, è quasi sempre scritto in un linguaggio come C o C ++ in cui l'efficienza è il numero 1, dove comprendere prevedibilmente l'esatta interazione tra software e hardware può essere buona capito e manipolato al massimo guadagno.

Adoro Smalltalk, Objective-C e avere un ricco sistema di runtime con riflessi, metadati, garbage collection, ecc. È possibile scrivere un codice straordinario per sfruttare queste funzionalità! Ma questo è semplicemente un livello superiore nello stack, un livello che deve poggiare su livelli inferiori, che a loro volta devono sedere sul sistema operativo e sull'hardware. E avremo sempre bisogno di un linguaggio che sia il più adatto per costruire quel livello: C ++ / C / Assembler.

Addendum: C ++ 11/14 sta continuando ad espandere la capacità di C ++ di supportare sistemi e astrazioni di livello superiore. Threading, sincronizzazione, modelli di memoria precisi, definizioni di macchine astratte più precise stanno consentendo agli sviluppatori di C ++ di realizzare molte delle astrazioni di alto livello su cui alcuni di questi linguaggi solo di alto livello avevano un dominio esclusivo, pur continuando a fornire quasi prestazioni del metallo ed eccellente prevedibilità (ovvero sottosistemi di runtime minimi). Forse le strutture di riflessione saranno abilitate in modo selettivo in una futura revisione del C ++, per coloro che lo desiderano - o forse una libreria fornirà tali servizi di runtime (forse ce n'è uno ora, o l'inizio di uno in fase di potenziamento?).


Il tuo punto sul runtime di una lingua che deve essere compilato in un'altra lingua non è vero nel caso di Objective-C, poiché il suo runtime è scritto in C (di cui Objective-C è un superset).
Richard J. Ross III,

Questa è una distinzione senza differenze. Che differenza fa, alla fine, il sottosistema di runtime utilizzato da Objective-C non è in realtà scritto in Objective-C, ma piuttosto in C?
Mordachai,

3
Mi dispiace; ma fintanto che lo colleghi correttamente, puoi compilare un programma obiettivo-c in C, infatti l'ho fatto qui: stackoverflow.com/a/10290255/427309 . Tutta la tua affermazione sopra è falsa. Il runtime è completamente accessibile tramite C, ed è una delle cose che lo rende un linguaggio dinamico così potente.
Richard J. Ross III,

1
"C runtime" è solo una libreria dinamica contenente il codice per la libreria standard C. Lo stesso vale per il "runtime C ++". È abbastanza diverso da un sistema di runtime come quello di Objective-C. Inoltre ... anche se suppongo che potresti tecnicamente usare il runtime Objective-C in C, è ancora solo un programma C che utilizza il runtime Objective-C - non puoi compilare un vero programma Objective-C in C.
celticminstrel

2
C ++ 11 con un modello di memoria + atomics lo rende più simile a un assemblatore portatile. Quelle non sono cose di alto livello, sono cose di basso livello per le quali in C ++ in precedenza mancava il supporto portatile. Ma la quantità di UB in C ++ se si fa qualcosa di sbagliato lo rende molto diverso dai linguaggi basati su VM come Java e anche da qualsiasi linguaggio assembly specifico. ad esempio, sign-overflow è totalmente UB nel sorgente C ++ e il compilatore può ottimizzare in base a quel fatto anche se la compilazione per dire diciamo x86, ma in asm su quasi tutte le piattaforme andrà semplicemente a finire. Il C ++ moderno è molto lontano da un linguaggio di assemblaggio portatile.
Peter Cordes,

11

Se vuoi davvero capire le decisioni di progettazione relative al C ++, trova una copia del Manuale di riferimento The Annotated C ++ di Ellis e Stroustrup. NON è aggiornato con lo standard più recente, ma passa attraverso lo standard originale e spiega come funzionano le cose e spesso, come sono andate in quel modo.


6
Anche Design ed Evolution di C ++ di Stroustrup
James Hopkin,

9

La riflessione per i linguaggi che lo riguardano riguarda la quantità di codice sorgente che il compilatore è disposto a lasciare nel codice oggetto per abilitare la riflessione e la quantità di macchine di analisi disponibili per interpretare tali informazioni riflesse. A meno che il compilatore non mantenga tutto il codice sorgente, la riflessione sarà limitata nella sua capacità di analizzare i fatti disponibili sul codice sorgente.

Il compilatore C ++ non mantiene nulla (beh, ignorando RTTI), quindi non si ottiene la riflessione nel linguaggio. (I compilatori Java e C # mantengono solo classe, nomi di metodi e tipi restituiti, quindi ottieni un po 'di dati di riflessione, ma non puoi ispezionare espressioni o struttura del programma, e ciò significa che anche in quei linguaggi "abilitati alla riflessione" il le informazioni che puoi ottenere sono piuttosto scarse e di conseguenza non puoi davvero fare molte analisi).

Ma si può fare un passo fuori la lingua e ottenere piena capacità di riflessione. La risposta a un'altra discussione di overflow dello stack sulla riflessione in C ne discute.


7

La riflessione può essere ed è stata implementata in c ++ in precedenza.

Non è una funzionalità c ++ nativa perché ha un costo elevato (memoria e velocità) che non dovrebbe essere impostato di default dalla lingua - la lingua è orientata alle "massime prestazioni di default".

Poiché non dovresti pagare per ciò che non ti serve e, come dici tu stesso, è necessario più negli editor che in altre applicazioni, quindi dovrebbe essere implementato solo dove ne hai bisogno e non "forzato" a tutto il codice ( non hai bisogno di riflettere su tutti i dati con cui lavorerai in un editor o in un'altra applicazione simile).


3
e non spedisci simboli perché consentirebbe ai tuoi clienti / concorrenti di guardare il tuo codice ... questo è spesso considerato una cosa negativa.
gbjbaanb,

Hai ragione, non ho nemmeno
pensato al

6

Il motivo per cui C ++ non riflette è che ciò richiederebbe ai compilatori di aggiungere informazioni sui simboli ai file oggetto, come ciò che i membri hanno un tipo di classe, informazioni sui membri, sulle funzioni e tutto il resto. Ciò essenzialmente renderebbe inutili i file, poiché le informazioni fornite dalle dichiarazioni verrebbero quindi lette da quei file oggetto (moduli allora). In C ++, una definizione di tipo può verificarsi più volte in un programma includendo le rispettive intestazioni (a condizione che tutte queste definizioni siano uguali), quindi si dovrebbe decidere dove inserire le informazioni su quel tipo, proprio come nominarne una complicazione qui. L'ottimizzazione aggressiva fatta da un compilatore C ++, che può ottimizzare dozzine di istanze di template di classe, è un altro punto di forza. È possibile, ma poiché C ++ è compatibile con C,


1
Non capisco come l'ottimizzazione aggressiva del compilatore sia un punto di forza. Puoi elaborare? Se il linker è in grado di rimuovere definizioni duplicate di funzioni incorporate, qual è il problema con le informazioni di riflessione duplicate? Le informazioni sui simboli non vengono comunque aggiunte ai file oggetto, per i debugger?
Rob Kennedy,

1
Il problema è che le informazioni di riflessione potrebbero non essere valide. Se il compilatore elimina l'80% delle definizioni della classe, cosa diranno i metadati della riflessione? In C # e Java, il linguaggio garantisce che se si definisce una classe, questa rimane definita. C ++ consente al compilatore di ottimizzarlo.
jalf

1
@Rob, le ottimizzazioni sono un altro punto, non legate alla complicazione delle classi multiple. Vedi il commento di @ jalf (e la sua risposta) per quello che intendevo dire.
Johannes Schaub - lett.

4
Se creo un'istanza di riflesso <T>, non gettare via nessuna informazione di T. Questo non sembra un problema irrisolvibile.
Joseph Garvin,

3

Ci sono tonnellate di casi per usare la riflessione in C ++ che non possono essere adeguatamente affrontati usando costrutti di tempo di compilazione come la meta-programmazione di template.

N3340 propone rich pointers come un modo per introdurre la riflessione in C ++. Tra le altre cose, risolve il problema del mancato pagamento di una funzionalità a meno che non venga utilizzata.


2

Secondo Alistair Cockburn, il sottotipo non può essere garantito in un ambiente riflettente .

La riflessione è più rilevante per i sistemi di tipizzazione latenti. In C ++, sai che tipo hai e sai cosa puoi farci.


Più in generale, la possibilità di verificare l'esistenza di una funzionalità che non esiste senza introdurre Undefined Behavior rende possibile che l'aggiunta di tale funzionalità a una versione successiva di una classe cambierà il comportamento ben definito dei programmi preesistenti e di conseguenza rende impossibile garantire che l'aggiunta di tale funzione non "rompa" qualcosa.
supercat

2

La riflessione potrebbe essere facoltativa, come una direttiva preprocessore. Qualcosa di simile a

#pragma enable reflection

In questo modo possiamo avere il meglio di entrambi i mondi, senza questo pragma le librerie verrebbero create senza riflessione (senza alcun sovraccarico come discusso), quindi spetterebbe al singolo sviluppatore se vogliono velocità o facilità d'uso.


2

Se C ++ potesse avere:

  • dati dei membri della classe per nomi di variabili, tipi di variabili e constmodificatore
  • un iteratore di argomenti di funzione (solo posizione anziché nome)
  • dati dei membri della classe per i nomi delle funzioni, il tipo restituito e il constmodificatore
  • elenco di classi principali (nello stesso ordine definito)
  • dati per membri modello e classi principali; il modello espanso (il che significa che il tipo effettivo sarebbe disponibile per l'API di riflessione e non le "informazioni del modello su come arrivarci")

Ciò sarebbe sufficiente per creare librerie molto facili da usare al punto cruciale dell'elaborazione dei dati senza nome che è così prevalente nelle odierne applicazioni web e di database (tutti gli orm, i meccanismi di messaggistica, i parser xml / json, la serializzazione dei dati, ecc.).

Ad esempio, le informazioni di base supportate dalla Q_PROPERTYmacro (parte di Qt Framework) http://qt.nokia.com/doc/4.5/properties.html espanse per coprire i metodi di classe ed e) - sarebbero straordinariamente vantaggiose per C ++ e per la comunità del software in generale.

Certamente la riflessione a cui mi riferisco non coprirebbe il significato semantico o questioni più complesse (come i numeri delle righe del codice sorgente dei commenti, l'analisi del flusso di dati, ecc.) - ma non penso nemmeno che siano necessari per far parte di uno standard linguistico.


@Vlad: Sì, se si aggiungono funzionalità che supportano la riflessione nella lingua, si ottiene una riflessione nella lingua. Ciò è probabile che accada solo se il comitato linguistico lo decreta, e penso che non lo siano dal 2011, e dubito che ci sarà un altro standard C ++ prima del 2020 d.C. Quindi, bel pensiero. Nel frattempo, se vuoi fare progressi, dovrai probabilmente uscire da C ++.
Ira Baxter,


0

Riflessione in C ++, credo sia di fondamentale importanza se il C ++ deve essere usato come linguaggio per l'accesso al database, la gestione delle sessioni Web / lo sviluppo di http e GUI. La mancanza di riflessione impedisce gli ORM (come Hibernate o LINQ), i parser XML e JSON che instanciano le classi, la serializzazione dei dati e molti altri aspetti (in cui i dati inizialmente non tipizzati devono essere utilizzati per creare un'istanza di una classe).

Un time switch di compilazione disponibile per uno sviluppatore di software durante il processo di compilazione può essere utilizzato per eliminare questo problema di "pagamento per ciò che si utilizza".

Se un sviluppatore di firmware non ha bisogno del riflesso per leggere i dati da una porta seriale, quindi non utilizzare lo switch. Ma come sviluppatore di database che desidera continuare a utilizzare il C ++, sono costantemente in fase di sviluppo di un codice orribile, difficile da mantenere, che mappa i dati tra membri dei dati e costrutti di database.

Né la serializzazione Boost né altri meccanismi stanno realmente risolvendo la riflessione - deve essere fatta dal compilatore - e una volta fatto il C ++ verrà ripreso nelle scuole e utilizzato nei software che si occupano dell'elaborazione dei dati

Per me questo numero 1 (e le primitive threading ingenui è il numero 2).


4
Chi ha detto che C ++ deve essere usato come linguaggio per DB Access, Web session hnadling o gui dev? Ci sono molte lingue molto migliori da usare per quel tipo di cose. E un interruttore di compilazione non risolverà il problema. Di solito, la decisione di abilitare o disabilitare la riflessione non sarà basata su un singolo file. Potrebbe funzionare se fosse abilitato su singoli tipi. Se il programmatore può specificare con un attributo o simile durante la definizione di un tipo, se generare o meno metadati di riflessione per esso. Ma un passaggio globale? Avresti paralizzato il 90% del lnaguage solo per renderlo più semplice.
jalf,

Quindi, se voglio un programma multipiattaforma e avere accesso a una GUI, cosa dovrei usare? L'inflessibile swing di Java? Le finestre solo C #? Ma la verità dovrebbe essere detta, e la verità è che ci sono molti programmi che sono compilati in codice eseguibile e offrono un'interfaccia gui e accesso ai database, quindi devono usare un po 'di database e supporto gui ... E non sono t usando QT. (avrebbe dovuto essere chiamato MT (monster toolkit))
Coyote21

1
@ Coyote21: C # non è stato Windows solo per anni. (Anche se non sono un fan di Mono, funziona abbastanza bene per la maggior parte delle cose.) E Swing non è l'unico toolkit GUI per Java. A dire il vero, uno dei due sarebbe una scelta migliore se si desidera multipiattaforma. Il C ++ avrà quasi sempre parti specifiche della piattaforma qui o là se stai facendo qualcosa di non banale.
cHao,

Non c'è motivo per cui hai bisogno di riflessione per ORM. Puoi ottenere tutto ciò con i modelli. Ci sono molti framework che forniscono ORM per C ++.
MrFox,

0

È fondamentalmente perché è un "extra opzionale". Molte persone scelgono C ++ su linguaggi come Java e C # in modo da avere un maggiore controllo sull'output del compilatore, ad esempio un programma più piccolo e / o più veloce.

Se si sceglie di aggiungere la riflessione, sono disponibili varie soluzioni .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.