Ответ 1
В наши дни с constexpr
и бит twiddling hacks вы можете просто
constexpr bool is_powerof2(int v) {
return v && ((v & (v - 1)) == 0);
}
Я хочу создать структуру, которая статически ставит массив из 2 ^ N байтов, но я не хочу, чтобы пользователи этой структуры указывали этот размер как экспонента. Пример:
my_stupid_array<char, 32> a1; // I want this!
my_stupid_array<char, 5> a2; // And not this...
Как проверить, является ли этот параметр шаблона мощностью двух и предупреждать пользователя с хорошим сообщением об этом?
Я смог проверить это с помощью простого шаблона:
template<int N>
struct is_power_of_two {
enum {val = (N >= 1) & !(N & (N - 1))};
};
Однако я не могу предупредить пользователя об этом с помощью разумного сообщения. Любые идеи?
ИЗМЕНИТЬ
Исправлен двусмысленный пример.
ИЗМЕНИТЬ
1 - действительно сила двух. Исправлено это!:)
ИЗМЕНИТЬ
Используя BOOST_STATIC_ASSERT, я получаю эту ошибку компиляции для этого кода с помощью GCC:
template<int N>
struct is_power_of_two {
enum {val = (N >= 1) & !(N & (N - 1))};
BOOST_STATIC_ASSERT(val);
};
Ошибка
..\main.cpp:29:1: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'
ИЗМЕНИТЬ
О, я понял. Это было сообщение, которое я должен получить, когда утверждение терпит неудачу. Но это не дает пользователю разумного сообщения.: (
В наши дни с constexpr
и бит twiddling hacks вы можете просто
constexpr bool is_powerof2(int v) {
return v && ((v & (v - 1)) == 0);
}
static_assert для спасения (только С++ 11, uncomment BOOST_STATIC_ASSERT для С++ 03):
#include<iostream>
// #include <boost/static_assert.hpp>
template<int N>
struct is_power_of_two {
enum {val = N && !(N & (N - 1))};
static_assert(val, "should use a power of 2 as template parameter");
// BOOST_STATIC_ASSERT(val); // without C++11 support, won't take a string message
};
int main()
{
std::cout << is_power_of_two<2>::val << "\n";
std::cout << is_power_of_two<3>::val << "\n";
}
UPDATE1: другая идея (я знаю, что вы этого не хотите, но для больших экспонентов намного проще):
template<int N>
make_power_of_two
{
enum { val = 1 << N };
};
my_stupid_array<char, make_power_of_two<5>::val > a1; // size 2^5 = 32
UPDATE2: на основе комментариев @sehe в чате вы можете сделать это для функций constexpr
, а также
constexpr bool is_power_of_two(int x)
{
return x && ((x & (x-1)) == 0);
}
Вы можете использовать static_assert
для сообщения об ошибке:
template<int N>
struct is_power_of_two {
static_assert((N > 1) & !(N & (N - 1)), "Template parameter must be a power of two.");
};