Domanda

Ho cercato di scrivere una funzione che restituisce un intero con solo il bit più alto del set di ingresso, utilizzando un C ++ 0x constexpr.

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

In questo modo un guasto in fase di compilazione con gcc 4.6.1.

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

Si noti che funziona senza l'constexpr parola chiave.

Le mie domande sono:

Perché questo non funziona? Vedo che operatore | = non è un constexpr, ma cosa importa per tipi built-in

?

C'è un modo facile scrivere questa funzione come constexpr? Vorrei che fosse ragionevole efficienza in fase di esecuzione, e mi preoccupo un po 'di leggibilità.

È stato utile?

Soluzione

(Not tested on GCC because I don't have 4.6, but I've verified that the algorithm is correct.)

To use constexpr you must not have assignments. Therefore, you often have to write in functional form with recursion:

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

You can check C++0x §[expr.const]/2 to see what expressions cannot be used in a constexpr function. In particular, the second to last item is "an assignment or a compound assignment".

Altri suggerimenti

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

Each level of recursion clears the rightmost bit that was set, when the final bit would be cleared, only the highest bit remained, so it's returned.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top