Espansione macro C / C ++ vs. generazione di codice
-
05-07-2019 - |
Domanda
Espansione sia macro che amp; La generazione del codice ha pro e amp; cons. Qual è il tuo approccio preferito e perché? Quando dovremmo scegliere l'uno rispetto all'altro? Si prega gentilmente di avvisare. Grazie!
L'espansione macro può essere molto utile & amp; utile: http://dtemplatelib.sourceforge.net/table.htm
vs
Mentre la generazione del codice ti dà un sacco di codice carino: http://code.google.com/p/protobuf/ http://incubator.apache.org/thrift/
Soluzione
È un compromesso. Lasciami fare un esempio. Mi sono imbattuto nella tecnica di esecuzione differenziale intorno al 1985, e penso che sia davvero buono strumento per la programmazione delle interfacce utente. Fondamentalmente, ci vogliono semplici programmi strutturati come questo:
void Foo(..args..){
x = y;
if (..some test..){
Bar(arg1, ...)
}
while(..another test..){
...
}
...
}
e muck con la struttura di controllo in questo modo:
void deFoo(..args..){
if (mode & 1){x = y;}
{int svmode = mode; if (deIf(..some test..)){
deBar(((mode & 1) arg1 : 0), ...)
} mode = svmode;}
{int svmode = mode; while(deIf(..another test..)){
...
} mode = svmode;}
...
}
Ora, un ottimo modo per farlo sarebbe quello di scrivere un parser per C o qualunque sia la lingua di base, e quindi camminare sull'albero di analisi, generando il codice che desidero. (Quando l'ho fatto a Lisp, quella parte è stata facile.)
Ma chi vuole scrivere un parser per C, C ++ o altro?
Quindi, invece, scrivo solo macro in modo da poter scrivere il codice in questo modo:
void deFoo(..args..){
PROTECT(x = y);
IF(..some test..)
deBar(PROTECT(arg1), ...)
END
WHILE(..another test..)
...
END
...
}
Tuttavia, quando lo faccio in C #, qualcuno nella loro saggezza ha deciso che le macro erano cattive e non voglio scrivere un parser C #, quindi devo fare la generazione del codice a mano. Questo è un dolore reale, ma ne vale ancora la pena rispetto al solito modo di codificare queste cose.
Altri suggerimenti
Per c ++ preferisco la metaprogrammazione dei modelli o la generazione di codice rispetto alle macro, ma le macro hanno ancora i loro usi.
L'esempio che hai fornito con dbtemplatelib potrebbe essere coperto con c ++ 0x Variadic Modelli , con vantaggi aggiuntivi come il controllo del tipo ecc.
In C o C ++, l'espansione delle macro è notoriamente difficile da eseguire il debug. D'altra parte, scrivere un generatore di codice è più facile da eseguire il debug perché è un programma separato in sé.
Tuttavia, dovresti essere consapevole che questa è solo una limitazione del preprocessore C. Ad esempio, nella famiglia di lingue Lisp, l'espansione delle macro è generazione di codice, sono esattamente la stessa cosa. Per scrivere una macro, scrivi un programma (in Lisp) per trasformare l'input S-expression in un'altra espressione S, che viene quindi passata al compilatore.
Entrambi hanno i loro problemi. A differenza delle macro, la generazione di codice può produrre codice leggibile e debuggable (è anche una parola?), Ma è meno flessibile e più difficile da modificare.