How do I check if a template parameter is a power of two?

后端 未结 3 912
刺人心
刺人心 2021-02-05 10:47

I want to create a structure that allocates statically an array of 2^N bytes, but I don\'t want the users of this structure to specify this size as the exponent

相关标签:
3条回答
  • 2021-02-05 11:31

    These days, with constexpr and the bit twiddling hacks you can just

    constexpr bool is_powerof2(int v) {
        return v && ((v & (v - 1)) == 0);
    }
    
    0 讨论(0)
  • 2021-02-05 11:40

    static_assert to the rescue (C++11 only, uncomment BOOST_STATIC_ASSERT for C++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";
    }
    

    Ideone output for C++11

    Ideone output for C++03

    UPDATE1: other idea (I know you don't want this, but it is a lot easier for large exponents):

    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: based on comments by @sehe in the chat, you can do this for constexpr functions as well

    constexpr bool is_power_of_two(int x)
    {
        return x && ((x & (x-1)) == 0);
    }
    
    0 讨论(0)
  • 2021-02-05 11:45

    You can use static_assert to provide an error message:

    template<int N>
    struct is_power_of_two {
        static_assert((N > 1) & !(N & (N - 1)), "Template parameter must be a power of two.");
    };
    
    0 讨论(0)
提交回复
热议问题