2012-05-14 10 views
15

मैं ऐसी संरचना बनाना चाहता हूं जो स्थिर रूप से 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))}; 
}; 

हालांकि, मैं एक समझदार संदेश के साथ इस बारे में उपयोगकर्ता को सचेत करने में असमर्थ हूँ। कोई विचार?

संपादित

अस्पष्ट उदाहरण फिक्स्ड।

संपादित

1 दो वास्तव में की एक शक्ति है। फिक्स्ड कि! :)

संपादित

BOOST_STATIC_ASSERT का उपयोग करना, मैं जीसीसी के साथ इस कोड के लिए इस संकलन त्रुटि हो रही है:

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

संपादित करें

ओह, मुझे यह मिल गया। यही वह संदेश था जिसे मैं असफल होने पर प्राप्त करना चाहता था। लेकिन यह उपयोगकर्ता को कुछ सौ संदेश देने में विफल रहता है।:(बचाव के लिए

+6

8 2 की शक्ति है ... –

+0

यह पैरामीटर के रूप में एक्सपोनेंट का एक उदाहरण के रूप में है। 2^8 = 256 – jrok

+0

> 'my_stupid_array a2; // और यह नहीं ... 'ऐसा क्यों नहीं? – triclosan

उत्तर

14

इन दिनों, constexpr और bit twiddling hacks के साथ आप केवल

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

यह वास्तविक समाधान है। – plasmacel

21

static_assert (सी ++ 11 केवल, टिप्पणी हटाएं के लिए सी ++ 03 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

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

इसमें शामिल किया। सी ++ 03 के लिए BOOST_STATIC_ASSERT का उल्लेख भी हो सकता है। – jrok

+0

दमनित। बस [यह लिंक] देने के बारे में था (http://www.boost.org/doc/libs/1_49_0/doc/html/boost_staticassert.html)। मुझे तेज़ी से टाइप करना सीखना है। –

+1

मेरा एम्बेडेड कंपाइलर अभी तक सी ++ 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 यहां थोड़ा सा twiddling हैक्स: http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2।'Constexpr' के आधार पर अपना स्वयं का संस्करण पोस्ट किया:/ – sehe

संबंधित मुद्दे

 संबंधित मुद्दे