2

qui est le code:C++ C1061 d'erreur fatale avec un grand interrupteur, metaprogramming

static inline void 
shrinkData(const vector<Data> &data, unsigned short shrinkType){ 
    #define CASE_N(N) \ 
    case(N): \ 
     ptr = MemoryManager::requestMemory(n*sizeof(ShrinkData<N>)); \ 
     for(int i=0; i<n; i++){ \ 
      new(ptr) ShrinkData<N>(data[i]); \ 
      ptr+=sizeof(ShrinkData<N>); \ 
     } \ 
     return; 


    int n = data.size(); 
    char* ptr; 

    switch(shrinkType){ 
    case(0): 
     return; 
    CASE_N(1) 
    CASE_N(2) 
    CASE_N(3) 
    .... 
    CASE_N(255) 
} 

maintenant j'obtenir une fatale "erreur C1061: limite du compilateur: blocs imbriqués trop profondément" en ligne CASE_N (124)

quelqu'un peut s'il vous plaît dites-moi pourquoi cela arrive? En fait, la nidification ne devrait pas être plus profonde que 2, non?

Merci!

// edit: le constructeur a demandé (le constructeur fonctionne très bien sans cette fonction de commutation)

enum {//maximally 16 to fit in a unsigned short! 
    EID_POSITION  = 1, //bit1 
    EID_T    = 2, //bit2 
    EID_GEOMNORMAL  = 4, //bit3 
    EID_NORMAL   = 8, //bit4 
    EID_TANGENTS  = 16, //bit5 
    EID_TEXCOORDS  = 32, //bit6 
    EID_RAYDIR   = 64, //bit7 
    EID_RECURSIONDEPTH = 128 //bit8 
}; 



template<unsigned, unsigned> 
struct IDataMember{ 
    IDataMember(){} 
    IDataMember(const Data &iData){} 
}; 


template<> 
struct IDataMember<EID_POSITION, EID_POSITION>{ 
    IDataMember(): position(Vector3(0,0,0)){} 
    IDataMember(const Data &iData):position(iData.position){} 
    Vector3 position; 
}; 

... le même genre de spécialisation de modèle pour chaque type dans les énumérations ...

template<unsigned members> 
struct ShrinkData 
    :public IDataMember<members & EID_POSITION, EID_POSITION> 
    ,public IDataMember<members & EID_T, EID_T> 
    ,public IDataMember<members & EID_GEOMNORMAL, EID_GEOMNORMAL> 
    ,public IDataMember<members & EID_NORMAL, EID_NORMAL> 
    ,public IDataMember<members & EID_TANGENTS, EID_TANGENTS> 
    ,public IDataMember<members & EID_TEXCOORDS, EID_TEXCOORDS> 
    ,public IDataMember<members & EID_RAYDIR, EID_RAYDIR> 
    ,public IDataMember<members & EID_RECURSIONDEPTH, EID_RECURSIONDEPTH> 
{ 
    ShrinkData() 
     :IDataMember<members & EID_POSITION, EID_POSITION>() 
     ,IDataMember<members & EID_T, EID_T>() 
     ,IDataMember<members & EID_GEOMNORMAL, EID_GEOMNORMAL>() 
     ,IDataMember<members & EID_NORMAL, EID_NORMAL>() 
     ,IDataMember<members & EID_TANGENTS, EID_TANGENTS>() 
     ,IDataMember<members & EID_TEXCOORDS, EID_TEXCOORDS>() 
     ,IDataMember<members & EID_RAYDIR, EID_RAYDIR>() 
     ,IDataMember<members & EID_RECURSIONDEPTH, EID_RECURSIONDEPTH>(){} 


    ShrinkData(const Data &iData) 
     :IDataMember<members & EID_POSITION, EID_POSITION>(iData) 
     ,IDataMember<members & EID_T, EID_T>(iData) 
     ,IDataMember<members & EID_GEOMNORMAL, EID_GEOMNORMAL>(iData) 
     ,IDataMember<members & EID_NORMAL, EID_NORMAL>(iData) 
     ,IDataMember<members & EID_TANGENTS, EID_TANGENTS>(iData) 
     ,IDataMember<members & EID_TEXCOORDS, EID_TEXCOORDS>(iData) 
     ,IDataMember<members & EID_RAYDIR, EID_RAYDIR>(iData) 
     ,IDataMember<members & EID_RECURSIONDEPTH, EID_RECURSIONDEPTH>(iData){} 

}; 
+0

Vous pouvez indiquer la version exacte du compilateur. – sbi

+0

Pouvons-nous voir le constructeur? –

+0

désolé, comment puis-je comprendre cela? Je travaille avec Visual Studio 2008 Professional – Mat

Répondre

2

Selon cette link il y a une « fonction » dans le compilateur qui permet uniquement pour le nombre limité de boucles. Je ne suis jamais arrivé à moi. Essayez de mettre l'initialisation de ptr et la suivante pour la boucle dans un bloc. Une autre solution consiste à créer la fonction de modèle qui couvre l'extrait complet, de sorte que la macro devient quelque chose comme ceci:

#define CASE_N(N) \ 
case(N): \ 
    ptr = requestAndInitialize<N>(data); \ 
    return; 
+0

hey qui a vraiment fait l'affaire! mettre tout ce qui suit le "cas (N):" dans un bloc le fait compiler très bien! Quelqu'un a une idée quelle est la différence ??? – Mat

+0

Je suppose que ce compilateur suit des boucles consécutives dans un but précis (pour l'optimisation peut-être). Les boucles dans des blocs séparés ne sont pas consécutives. Pas dans le même champ. – Dialecticus

+0

@Mat: Si vous passez votre souris sur le bouton "up-vote", vous verrez un message disant "Cette réponse est utile". Et c'est exactement ce que ce bouton est pour: vous cliquez dessus quand vous pensez qu'une réponse est utile. Il m'échappe juste comment quelqu'un pourrait célébrer une bonne réponse sans le mettre aussi à la hausse ... – sbi

0

Juste spéculer, mais la fonction est étiquetée en ligne et elle utilise également des modèles, peut-être que cela fait partie de l'origine de l'imbrication supplémentaire. Cependant, plus probablement OMI, la limite de ressources que vous frappez n'est probablement pas aussi claire que les "niveaux d'imbrication" mais plutôt la cause la plus fréquente de frappe, c'est ce que le message d'erreur fait référence à.

2

Je suppose que ce message d'erreur est faux. Il y a probablement une limite de compilateur, mais il est peu probable que le bloc soit imbriqué.

Quoi qu'il en soit, que se passe-t-il si vous mettez ce code pour chaque case dans son propre modèle de fonction et que vous l'appelez simplement?
De même, l'introduction de cette fonction ne vous apportera probablement rien car elle demandera de la mémoire et exécutera une boucle. La surcharge des appels de fonction doit être négligeable par rapport à cela. (Peu importe le nombre d'itérations de cette boucle, la seule mise en place est probablement moitié moins chère que d'appeler une fonction.)
Enfin, j'essaierai de me débarrasser de la macro, juste au cas où.

Le code pourrait alors ressembler à ceci:

// Beware, brain-compiled code ahead! 
template<unsigned short N> 
void do_it(int n) 
{ 
    char* ptr = MemoryManager::requestMemory(n*sizeof(ShrinkData<N>)); 
    for(int i=0; i<n; i++){ 
    new(ptr) ShrinkData<N>(data[i]); 
    ptr+=sizeof(ShrinkData<N>); 
    } 
} 

static void 
shrinkData(const vector<Data> &data, unsigned short shrinkType) 
{ 
    const std::vector<Data>::size_type n = data.size(); 
    switch(shrinkType){ 
    case 0: break 
    case 1: do_it< 1>(n); break; 
    case 2: do_it< 2>(n); break; 
    . 
    . 
    . 
    case 254: do_it<254>(n); break; 
    case 255: do_it<255>(n); break; 
} 
0

Je viens suis tombé sur ceci dans un code généré automatiquement; pour les boucles plutôt que d'un commutateur, mais le même problème. Plutôt que de mettre toutes les boucles dans leurs propres blocs - rendant le code un peu plus laid dans le processus - j'ai apparemment résolu le problème en déplaçant la déclaration de l'itérateur en dehors des boucles, style C.

Je pense que le problème pourrait réapparaître si nous ajoutons trop de boucles supplémentaires, car je pense que c'est dû au manque d'espace pour stocker les données d'oscilloscope, mais c'est beaucoup plus agréable entre-temps. Edit: bien sûr le problème est réapparu 1,5 ans plus tard. Et l'ajout du niveau d'imbrication supplémentaire l'a corrigé. Je suppose que cette réponse était plus pour mon propre bénéfice que n'importe qui d'autre.