2010-07-13 2 views
1

J'ai un code qui s'exécute sur un système embarqué et il doit fonctionner très rapidement. Je connais C et les macros, et ce projet particulier est codé principalement en C mais il utilise aussi des modèles C++ [de plus en plus]. Il y a une fonction en ligne:Utilisation de modèles C++ ou de macros pour la génération de la fonction de compilation

inline my_t read_memory(uint32 addr) { 
    #if (CURRENT_STATE & OPTIMIZE_BITMAP) 
    return readOptimized(addr); 
    #else 
    return MEMORY[addr]; 
    #endif 
} 

Cette fonction lit de la mémoire d'une manière optimisée ou la mode classique à base de l'état actuel et une image bitmap qui indique si vous souhaitez utiliser l'optimisation dans un état spécifique ou non.

#define STATE_A 0x0001 
#define STATE_B 0x0010 
#define STATE_C 0x0100 
#define STATE_D 0x1000 

#define OPTIMIZE_BITMAP 0x1010 // optimize states d and b 

et au cours de l'exécution (ok, compilation), j'ai essayé de redéfinir current_state comme ceci:

int main(){ 
    #define CURRENT_STATE STATE_A 
    do_a(); 
    #undef CURRENT_STATE 
    #define CURRENT_STATE STATE_B 
    do_b(); 
    .... 
} 

Toutes les fonctions do_X() font des appels read_memory(). Je ne pouvais pas faire fonctionner cette approche. La valeur de l'état actuel est toujours STATE_A comme je peux le voir lorsque j'utilise les instructions #warning. Ce n'est pas ma question, mais si vous pouvez m'aider avec cela, je serai heureux. Donc, ma question est, y at-il un moyen de faire ce genre de chose en utilisant des modèles au lieu de macros?

Encore plus d'infos: Je dois utiliser une fonction inline car je ne peux pas exporter MEMORY [] et c'est une fonction de bibliothèque. Je préfère vraiment ne pas modifier le prototype de la fonction (comme read_memory() ...) mais ça va le faire. Aussi, pardonnez mon obscurité.

merci beaucoup,

+1

Pourquoi voulez-vous utiliser des modèles pour cela? –

+0

C'est ce que je pouvais penser pour les décisions de temps de compilation que je ne veux pas décider en cours d'exécution. Mais je suis ouvert. – perreal

+1

OK, qu'est-ce qui vous fait penser qu'une décision d'exécution serait trop lente? Avez-vous décrit une telle chose? Nous voulons tous que notre code fonctionne "très rapidement" et 99,99% du temps c'est exactement ce qu'il fait, sans utilisation exotique de macros ou de modèles. –

Répondre

10

La fonction en ligne sera analysée une fois, au point dans l'unité de traduction où elle est déclarée, et l'état des macros à ce moment-là sera utilisé . Appeler la fonction plusieurs fois avec les macros définies différemment ne changera pas la définition de la fonction.

Vous peut faire avec un modèle bien --- si vous passez le « état actuel » en tant que paramètre de modèle, vous pouvez utiliser un autre instanciation à chaque point d'appel:

template<unsigned state> 
inline my_t read_memory(uint32 addr) { 
    if(state & OPTIMIZE_BITMAP) 
    return readOptimized(addr); 
    else 
    return MEMORY[addr]; 
} 

int main(){ 
    read_memory<STATE_A>(some_addr); 
    read_memory<STATE_B>(some_addr); 
    .... 
} 

Le compilateur se rendra compte que state & OPTIMIZE_BITMAP est une constante et optimiser l'une ou l'autre branche du if pour chaque instanciation de modèle.

+2

+1, nettement plus propre que la spécialisation :) –

+0

Et puisque 'state' et' OPTIMIZE_BITMAP' sont des constantes, il est très probable que le compilateur éliminera complètement le test et le code-barres, obtenant ainsi le même effet. –

5

Je pense que vous pouvez avoir de nombreux malentendus ce que le compilateur (ou plutôt, le préprocesseur) le fait aveC#defines.

Votre exemple (cité ci-dessous) n'est pas utile, car CURRENT_STATE n'est pas utilisé entre #define et #undef. Le préprocesseur n'exécute pas votre code, ou ne développe pas do_a() inline à ce stade. #defines et macro expansion ne peuvent se produire EXACTEMENT DANS L'ORDRE DES LIGNES DANS VOTRE SOURCE.

#define CURRENT_STATE STATE_A 
    do_a(); 
    #undef CURRENT_STATE 

Voici une solution basée sur le préprocesseur, si les modèles vous remplissent d'horreur. Supposons que do_a() utilise la version optimisée.

inline my_t read_memory(uint32 addr) 
{ 
    return MEMORY[addr]; 
} 

inline my_t read_memory_optimized(uint32 addr) 
{ 
    return readOptimized(addr); 
} 

Maintenant, créez DO_CONFIG.H

#if defined(DO_A) || (defined(DO_C) || ...) 
    #define READ_MEMORY read_memory_optimized 
#else 
    #define READ_MEMORY read_memory 

En DO_A.C, ajoutez au sommet

#define DO_A 
#include DO_CONFIG.H 

... et utiliser x=READ_MEMORY(addr) au lieu de x=read_memory(addr). Pour passer d'optimiser à la non-optimisé, il suffit de changer DO_CONFIG.H

+0

Je suis stupide évidemment, merci – perreal

+1

@perreal. Vous posez des questions ici. C'est SMART! – Roddy

+0

donc, peut-être quelque chose comme #define CURRENT_STATE STATE_A #include "usr_do_a.c" do_a(); #undef CURRENT_STATE ... fonctionnera? beaucoup de fichiers ... – perreal

Questions connexes