Frage

Ich bereite mich auf die Definition von vor Benutzerdefinierte Literale mit einer Variadische Vorlage

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

unsigned thirteen = 1101_binary;

GCC 4.7.0 unterstützt nicht operator "" Doch, aber ich kann dies bis dahin mit einer einfachen Funktion simulieren.

Leider ist meine Rekursion falsch. Ich kann mir keine schöne Art und Weise vorstellen, wie ich Verschieben:

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!
}

Was natürlich nicht ganz richtig ist:

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

Weil meine Rekursion die am weitesten am weitesten entfernten und nicht die am linken am weitesten rechts.

Es ist wahrscheinlich, dass ich winzig ist, aber ich kann es einfach nicht sehen.

  • Kann ich die Linie korrigieren? _bin<C>() | _bin<D,ES...>() << 1;?
  • Oder muss ich alles weiterleiten und danach alles umdrehen (nicht schön)?
  • Oder eine andere Art, die ich nicht sehen kann?

Aktualisieren: Ich konnte die Rekursion nicht umgekehrt falten, aber ich entdeckte sizeof.... Funktioniert, aber nicht perfekt. Gibt es eine andere Art und Weise?

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

Lösung

Bei jedem Schritt der Rekursion kennen Sie bereits den Rang der linken Ziffer.

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...>();
}

Andere Tipps

Parameterpakete sind relativ unflexibel und Sie schreiben normalerweise keine Algorithmen direkt darin. Variadische Funktionsvorlagen eignen sich gut zum Weiterleiten, aber ich würde das in ein überschaubareres Verpackung bekommen tuple Bevor Sie versuchen, es zu manipulieren.

Mit einem einfachen binary_string_value Metafunktion, wo der Platz der 1 an erster Stelle steht, und ein Generika tuple_reverse Metafunktion wäre das Muster

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;
}

Eine Möglichkeit wäre, einen Akkumulator zu verwenden:

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>());
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top