Frage

Ich habe versucht, eine Funktion zu schreiben, die eine Ganzzahl mit nur dem höchsten Bit des Eingangssatzes unter Verwendung eines C ++ 0x ConstExpr zurückgibt.

constexpr inline uint64_t
get_highest_bit(uint64_t p)
{
  return 
     (p|=(p>>1)),
     (p|=(p>>2)),
     (p|=(p>>4)),
     (p|=(p>>8)),
     (p|=(p>>16)),
     (p|=(p>>32)),
     (p-(p>>1));
}

Dies ergibt einen Kompilierungszeitausfall mit GCC 4.6.1.

error: expression ‘(p <unknown operator> ((p >> 1) | p))’ is not a constant-expression

Beachten Sie, dass es ohne das Keyword von Contexpr funktioniert.

Meine Fragen sind:

Warum geht das nicht? Ich kann sehen, dass Operator | = kein Contexpr ist, aber ist es für eingebaute Typen von Bedeutung?

Gibt es eine einfache Möglichkeit, diese Funktion als Contexpr zu schreiben? Ich möchte, dass es zur Laufzeit angemessen ist, und es ist mir ein wenig um die Lesbarkeit.

War es hilfreich?

Lösung

(Nicht auf GCC getestet, weil ich nicht 4.6 habe, aber ich habe überprüft, ob der Algorithmus korrekt ist.)

Benutzen constexpr Sie dürfen keine Aufgaben haben. Deshalb muss man oft einschreiben funktional Form mit Rekursion:

#include <cstdint>
#include <climits>

constexpr inline uint64_t highestBit(uint64_t p, int n = 1) {
    return n < sizeof(p)*CHAR_BIT ? highestBit(p | p >> n, n * 2) : p - (p >> 1);
}

int main() {
    static_assert(highestBit(7) == 4);
    static_assert(highestBit(5) == 4);
    static_assert(highestBit(0x381283) == 0x200000);
    return 0;
}

Sie können C ++ 0x § [expr.const]/2 überprüfen, um festzustellen, welche Ausdrücke in a nicht verwendet werden können constexpr Funktion. Insbesondere ist das zweite zu letztes Element "eine Zuordnung oder eine zusammengesetzte Zuordnung".

Andere Tipps

constexpr inline uint64_t highestBit(uint64_t p)
{
    return (p & (p-1))? highestBit(p & (p-1)): p;
}

Jedes Rekursionsniveau löscht das gesetzte rechts rechtliche Bit, wenn das letzte Bit gelöscht wird, nur das höchste Bit blieb, sodass es zurückgegeben wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top