Le fragment suivant renvoie la deuxième puissance la plus élevée de deux pour un entier (supposé non signé) de type T. Il le fait en déplaçant les bits de façon répétée. Pour toutes fins utiles, le type non signé utilisé dans la boucle de décalage de bits est suffisamment grand pour représenter un nombre (nominalement) de 65 536 bits. Pratiquement donc c'est bien de le laisser tel quel.C++ - Programmation générique - Sélection du type
template <class T>
T supremum_2(T k) {
if (k == T(0)) return T(1);
k--;
for (int i=1; i<sizeof(T)*8; i++) k |= k >> i;
return k+1;
}
Pour faire un travail professionnel, le type de compteur de boucle doit être choisie au moment de la compilation afin qu'il garantit de pouvoir couvrir jusqu'à sizeof (T) * 8 sans trop-plein. Cela peut-il être fait à la compilation en utilisant std :: numeric_traits?
Si c'est le cas, comment?
Conceptuellement Je voudrais pouvoir écrire quelque chose comme:
typedef unsigned_type_that_can_represent<sizeof(T)*8> counter_type;
...
...
for (counter_type i(1); i<sizeof(T)*8; i<<=1) k = k | k >> i;
...
Sur la base des discussions ci-dessous j'ai décidé d'ajouter le contexte suivant.
Autrement dit:
Comment pouvons-nous garantir pour sélectionner efficace (seulement aussi grand que ils ont besoin d'être) et les types appropriés pour le fonctionnement interne du code du modèle au moment de la compilation? Si nous nous trouvons en utilisant des types concrets dans le code de modèle nous pouvons faire des suppositions par inadvertance au sujet des types des calibres par l'intermédiaire d'une route potentiellement opaque. Par exemple, si nous devions coller (par exemple) un int pour le compteur, tout ira bien jusqu'à ce que quelqu'un utilise le code du template avec sa bibliothèque bigint. Cela pourrait représenter des entiers avec plus de chiffres binaires que ce qui peut être représenté par un int. Devrions-nous donc faire le type non signé longtemps? Cela ne fait que retarder le problème (mais pour longtemps)? Il y a des nuances de "640K - assez grand pour tout le monde" ou des tailles de tableaux statiques sur cette solution.
Le choix évident, mais quelque peu inefficace, dans ce cas est de définir le type du compteur comme étant le même que le type du nombre k. Il est (en principe) inefficace puisque nous demandons seulement que le compteur puisse représenter un nombre correspondant au nombre de bits de k. Il se peut que pour d'autres situations, ce soit la mauvaise chose à assumer.
Qu'en est-il du cas général? Il semble que la méta-programmation soit une approche appropriée. Comment garder ce "sens"? Peut-être, formellement, l'exigence est pour une fonction de compilation de mapper des exigences de type abstrait (potentiellement dérivées) sur les types.
Peut-être que c'est un travail pour YABL (Yet Another Boost Library)!
[Toutes mes excuses pour décousu]
J'aurais utilisé comme argument de modèle et spécialisé en fonction de cela. –
ouais. Je l'ai fait comme ça en premier (divisé par CHAR_BIT). Mais il s'est avéré que je devais faire des répétitions pour 3 et 4. Et s'il ajoute longtemps, il doit répéter pour tous 5, 6, 7 et 8 :) Donc j'ai pensé que je ferais mieux de le faire avec op> :) –
Si ma compréhension est correcte, cela se résoudra à un type basé sur le nombre minimum de bits requis - par exemple 32. Mon problème est un peu plus subtil que cela, car l'argument de votre paramètre de template je pense qu'il doit y avoir quelque chose d'autre qui nous indique le nombre minimum de bits requis pour représenter un entier donné. par exemple. select_t> :: type i (0); De cette façon, si T était (disons) un caractère, nous aurions seulement besoin d'un compteur qui serait capable de représenter jusqu'au nombre 8 (4 bits), donc le type de compteur pourrait être un type (minuscule) fictif. '. –