Question

Je me préparais pour la défintion de littéraux définis par l'utilisateur avec VARIADIC modèle

template<...>
unsigned operator "" _binary();

unsigned thirteen = 1101_binary;

GCC 4.7.0 ne supporte pas operator "" encore, mais je peux simuler cela avec une simple fonction jusque-là.

Hélas, mon récursion est le mauvais sens. Je ne peux pas penser à une façon agréable que je ne déplace pas les valeurs les plus à droite, mais l'extrême gauche :

template<char C> int _bin();
template<>       int _bin<'1'>() { return 1; }
template<>       int _bin<'0'>() { return 0; }

template<char C, char D, char... ES>
int _bin() {
    return _bin<C>() | _bin<D,ES...>() << 1; // <-- WRONG!
}

qui est bien sûr pas tout à fait raison:

int val13 = _bin<'1','1','0','1'>();  // <-- gives 10

parce que mes récursion déplace le plus à droite « 1 de plus éloignés, et non pas les plus à gauche ceux.

Il est sans doute que je petite chose, mais je ne peux pas le voir.

  • Puis-je corriger la ligne _bin<C>() | _bin<D,ES...>() << 1;?
  • Ou dois-je avant tout et tourner autour de tout par la suite (pas bien)?
  • Ou toute autre manière que je ne vois pas?

Mise à jour : Je ne pouvais pas plier la récursion l'inverse, mais j'ai découvert sizeof.... Fonctionne, mais pas parfait. Y at-il une autre façon?

template<char C, char D, char... ES>
int _bin() {
    return   _bin<C>() << (sizeof...(ES)+1) | _bin<D,ES...>() ;
}
Était-ce utile?

La solution

A une étape de la récursion vous connaissez déjà le rang du premier chiffre à gauche.

template<char C> int _bin();
template<>       int _bin<'1'>() { return 1; }
template<>       int _bin<'0'>() { return 0; }

template<char C, char D, char... ES>
int _bin() {
    return _bin<C>() << (1 + sizeof...(ES)) | _bin<D,ES...>();
}

Autres conseils

paquets de paramètres sont relativement rigides, et vous n'écrivent généralement pas des algorithmes directement en eux. modèles de fonction variadique sont bons pour le transfert, mais j'obtiendrais qui a emballé dans un tuple plus facile à gérer avant d'essayer de le manipuler.

Utilisation simple binary_string_value métafonction où la place du 1 vient en premier, et un tuple_reverse générique métafonction, le motif serait

template< char ... digit_pack >
constexpr unsigned long long _bin() {
    typedef std::tuple< std::integral_constant< digit_pack - '0' > ... > digit_tuple;
    return binary_string_value< typename tuple_reverse< digit_tuple >::type >::value;
}

Une possibilité serait d'utiliser un accumulateur:

template <char C>
int _binchar();
template<>
int _binchar<'0'>() { return 0; }
template<>
int _binchar<'1'>() { return 1; }

template<char C>
int _bin(int acc=0) {
   return (acc*2 + _binchar<C>());
}
template<char C, char D, char... ES>
int _bin(int acc=0) {
   return _bin<D, ES...>(acc*2 + _binchar<C>());
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top