Templatisierte zweiglose Int Max / Min-Funktion

8

Ich versuche, eine branchless-Funktion zu schreiben, um MAX oder MIN zweier Ganzzahlen zurückzugeben, ohne auf if (oder? :). Mit der üblichen Technik kann ich Mach das einfach genug für eine gegebene Wortgröße:

%Vor%

Nun, angenommen, argument , dass ich wirklich die Art von Anwendung auf der Art von In-Order-Prozessor schreibe, wo dies ist ist notwendig, meine Frage ist, ob es eine Möglichkeit gibt, C ++ - Vorlagen zu verwenden, um dies auf alle Größen von int zu verallgemeinern.

Der & gt; & gt; & gt; 31 -Schritt funktioniert natürlich nur für int32s, und obwohl ich Überladungen der Funktion für int8, int16 und int64 herauskopieren könnte, scheint es, als würde ich a verwenden Vorlagenfunktion stattdessen. Aber wie bekomme ich die Größe eines Template-Arguments in Bits ?

Gibt es einen besseren Weg, dies zu tun? Kann ich die Unterschrift der Maske T erzwingen? Wenn T nicht vorzeichenbehaftet ist, funktioniert der Maskenverschiebungsschritt nicht (weil es eine logische statt einer arithmetischen Verschiebung ist).

%Vor%

Und nachdem ich das oben Gesagte getan habe, kann ich verhindern, dass es für irgendetwas anderes als einen Integer-Typ (zB keine Floats oder Klassen) verwendet wird?

    
Crashworks 05.02.2009, 03:34
quelle

3 Antworten

8

Im Allgemeinen sieht es gut aus, aber für 100% Portabilität, ersetzen Sie diese 8 durch CHAR_BIT (oder numeric_limits :: max ()), da es nicht garantiert ist, dass Zeichen 8-Bit sind.

Jeder gute Compiler ist schlau genug, um alle mathematischen Konstanten zur Kompilierzeit zusammenzuführen.

Sie können das Signieren erzwingen, indem Sie eine Typ-Traits-Bibliothek verwenden. Das würde normalerweise so aussehen (vorausgesetzt, Ihre numeric_traits-Bibliothek heißt numeric_traits):

%Vor%

Ein Beispiel für einen manuell gerollten numeric_traits-Header könnte wie folgt aussehen: Ссылка (es gibt genug Platz für Ergänzungen, aber Sie bekommen die Idee).

oder besser noch boost:

%Vor%

EDIT: IIRC, signierte Rechtsverschiebungen müssen nicht arithmetisch sein. Es ist üblich, und sicherlich bei jedem Compiler, den ich verwendet habe. Aber ich glaube, dass der Standard es dem Compiler überlässt, ob Rechtsverschiebungen arithmetisch sind oder nicht. In meiner Kopie des Normentwurfs steht geschrieben:

  

Der Wert von E1 & gt; & gt; E2 ist E1   rechtsverschobene E2-Bitpositionen. Wenn E1   hat einen vorzeichenlosen Typ oder wenn E1 eine hat   signierter Typ und ein nicht negativer Wert,   Der Wert des Ergebnisses ist der   Integraler Bestandteil des Quotienten von E1   geteilt durch die Menge 2 erhöht auf   die Kraft E2. Wenn E1 einen signierten Typ hat   und ein negativer Wert, der sich ergibt   Wert ist Implementierung definiert .

Aber wie ich schon sagte, es funktioniert bei jedem Compiler, den ich gesehen habe :-p.

    
Evan Teran 05.02.2009, 03:47
quelle
2

Vielleicht möchten Sie sich die Boost.TypeTraits Bibliothek. Um festzustellen, ob ein Typ signiert ist, können Sie die is_signed verwenden Merkmal. Sie können auch in enable_if / disable_if nachsehen, um Überladungen für bestimmte Typen zu entfernen.

    
grepsedawk 05.02.2009 03:52
quelle
2

Hier ist ein weiterer Ansatz für max. und min. Was ist nett daran ist, dass es keine Bit-Tricks verwendet und Sie nichts über den Typ wissen müssen.

%Vor%     
Ambroz Bizjak 29.11.2012 02:12
quelle