2012-05-14 3 views
15

2^N 바이트 배열의 배열을 정적으로 할당하는 구조체를 만들고 싶지만이 구조체의 사용자가이 크기를 지수로 지정하는 것을 원하지 않습니다. 예 :이 템플릿 매개 변수는 두 의 전력이에 대한 좋은 메시지와 함께 사용자 경고를해서 인 경우템플릿 매개 변수의 출력이 2인지 확인하려면 어떻게합니까?

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

그러나, 나는 제정신 메시지와 함께 이것에 대해 사용자에게 경고 드릴 수 없습니다. 어떤 아이디어?

EDIT

모호한 예 수정.

편집

1 실제로 2의 거듭 제곱이다. 그것을 고쳤다! :) 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>' 

http://ideone.com/cMfEf

EDIT

아, 알겠습니다. 저것은 나가 주장이 실패 할 때 얻는 가정 된 메시지이었다. 그러나 그것은 사용자에게 정통 메시지를주지 못합니다.:(구조에

+6

8은 2의 거듭 제곱입니다 ... –

+0

이것은 매개 변수의 지수의 예를 의미합니다. 2^8 = 256 – jrok

+0

>'my_stupid_array a2; // 그리고 이건 ... 왜? – triclosan

답변

14

요즘은 constexprbit twiddling hacks을 사용하면

constexpr bool is_powerof2(int v) { 
    return v && ((v & (v - 1)) == 0); 
} 
+0

이것은 실제 솔루션입니다. – plasmacel

21

static_assert (C++ 03 C++ 11 만 주석 BOOST_STATIC_ASSERT) :

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

Ideone output for C++11

Ideone output for C++03

갱신 1 : 다른 생각 (당신이 이것을 원하지 않는다는 것을 압니다 만, 큰 지수의 경우 훨씬 쉽습니다) :

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

나를 이길. BOOST_STATIC_ASSERT for C++ 03을 언급 할 수도 있습니다. – jrok

+0

Damnit. 방금 [이 링크] (http://www.boost.org/doc/libs/1_49_0/doc/html/boost_staticassert.html)를 제공하려고했습니다. 빨리 입력하는 법을 배워야합니다. –

+1

내 임베디드 컴파일러는 아직 C++ 11을 수행하지 않습니다. 내가 부스트 대안을 시도하고 그것이 작동하는 경우이 답변을 추가합니다. – ivarec

9

오류 메시지가 제공하는 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."); 
}; 
+0

+1 http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2에서 더 많은 비트 해킹이 발생합니다.'constexpr'을 기반으로 내 자신의 버전을 게시 :/ – sehe

관련 문제