constexpr с оператором | = - PullRequest
       8

constexpr с оператором | =

2 голосов
/ 23 июля 2011

Я попытался написать функцию, которая возвращает целое число только с самым старшим битом входного набора, используя constexpr C ++ 0x.

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

Это дает сбой во время компиляции с использованием gcc4.6.1.

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

Обратите внимание, что это работает без ключевого слова constexpr.

Мои вопросы:

Почему это не работает?Я вижу, что operator | = не является constexpr, но имеет ли это значение для встроенных типов?

Есть ли простой способ написать эту функцию как constexpr?Я хотел бы, чтобы он был достаточно эффективным во время выполнения, и я немного беспокоюсь о читабельности.

Ответы [ 2 ]

8 голосов
/ 23 июля 2011

(Не проверено на GCC, потому что у меня нет 4.6, но я проверил, что алгоритм правильный.)

Для использования constexpr у вас не должно быть назначений.Поэтому вам часто приходится писать в функциональной форме с рекурсией:

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

Вы можете проверить C ++ 0x § [expr.const] / 2, чтобы увидеть, какие выражения нельзя использоватьв функции constexpr.В частности, вторым по последнему пункту является «назначение или составное назначение».

3 голосов
/ 23 июля 2011
constexpr inline uint64_t highestBit(uint64_t p)
{
    return (p & (p-1))? highestBit(p & (p-1)): p;
}

Каждый уровень рекурсии очищает самый правый бит, который был установлен, когда последний бит будет очищен, остался только самый старший бит, поэтому он возвращается.

...