2008-11-07 10 views
2

Existe-t-il un moyen de pré-calculer un tableau de valeurs basé sur des modèles? Dans l'exemple suivant, je voudrais que le tableau 'powers_of_2' ait 256 valeurs calculées au moment de la compilation si cela est possible sans avoir à taper toutes les valeurs.Comment précalculer un tableau de valeurs?

#include <iostream> 
using namespace std; 

template <int X, char Y> 
struct power { 
    enum { value = X * power<X,Y-1>::value }; 
}; 

template <int X> 
struct power<X,1> { 
    enum { value = X }; 
}; 

template <int X> 
struct power<X,0> { 
    enum { value = 1 }; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int powers_of_2[] = { power<2,0>::value, power<2,1>::value, ..., power<2,255>::value }; 
    cout << powers_of_2[1] << endl; 
    return 0; 
} 
+0

En fait maintenant que je regarde à nouveau votre question (autre que le problème de débordement), il semble que vous ayez déjà la réponse. ??? – grieve

Répondre

1

C'est exactement ce qu'une macro est utile pour ...

4

Sauf si vous prévoyez d'utiliser un gros paquet entier vous débordera le type entier à 2^32 (ou 2^64, en fonction) , mais pour répondre à votre vraie question, regardez cet article wikipedia sur template metaprogramming.

+0

J'ai modifié ma question pour que Y soit maintenant de type char au lieu de int. – Mike

+0

Si Y n'est pas un char non signé, ce qui semble ne pas l'être, alors votre plage pour Y est de -128 à 127. Même si Y est non signé, la plage est seulement de 0 à 255 (il vous manque 256). Même si X est toujours un nombre entier et il débordera à 2^32 ou 2^64 selon la machine et le compilateur. – grieve

+0

La métaprogrammation de modèle n'est pas suffisante pour une telle tâche. Même si les macros ne prennent pas en charge la récursivité, elles constituent la seule méthode viable pour implémenter la répétition d'instructions. –

0

Vous pouvez facilement écrire un petit script pour préremplir le tableau pour vous en utilisant votre langage de script préféré. Selon le compilateur et le préprocesseur que vous utilisez, vous devriez également pouvoir le faire en tant que macro.

1

Maintenir la valeur 2^255 nécessiterait 32 octets. Cela ne peut pas être tenu dans un int; vous auriez besoin d'un tableau char

typedef unsigned char BYTE32[32]; 
BYTE32 powers_of_2[256] = 
{ 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, 
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0}, 
// : 
// : 
    {32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
    {64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
    {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} 
}; 
0

Je suis d'accord avec Lokkju. Il n'est pas possible d'initialiser le tableau uniquement par métaprogrammation de template et les macros dans ce cas sont très utiles. Même les bibliothèques Boost utilisent des macros pour implémenter des instructions répétitives.

Des exemples de macros utiles sont disponibles ici: http://awgn.antifork.org/codes++/macro_template.h

1

Ce que je fais dans ce genre de situations est d'écrire un petit programme qui génère et écrit dans un fichier l'initialisation du tableau dans la source C++ et puis #include ce fichier. Cette technique est simple et efficace.

Questions connexes