polfosol ఠ_ఠ
polfosol ఠ_ఠ

Reputation: 1898

How to make a template with customized bit shift values

Suppose that I need a function template that does different amounts of bit shifts on different integer types. For example, if the input value n is of type char, the function does some calculations on n>>2 and n<<3. If it is short int, then the function uses n>>1 and n<<8. For int type, there would be n>>11 and n<<9, and so on. Of course, the values mentioned are just for example and there is no correlation between them and the size of int_type.

My suggestion for this problem was something like this:

template <typename Num_Type = char, int s1 = 2, int s2 = 3> void test1(Num_Type &n)
{
    // this is just an example code:
    int a = n >> s1,
        b = n << s2;
    // do some calculations on a and b
}

So I can use this template for different types of input value. But when I compile it, it gives me several warnings about undefined behavior in shift operations, because the value may be too big.

So the question can be asked in two forms:

  1. How can I customize bit-shift operations without getting "undefined behavior" warnings? or

  2. Can I have a limited data type, say intlength which can only have a specified range of numbers, say 0, 1, 2, ... , 31? I know it may sound stupid, but in this case, I can define the template as

    template <typename Num_Type = char, intlength s1 = 2, intlength s2 = 3> void test1(Num_Type &n)
    

and so the compiler should not complain about shift values.

Upvotes: 3

Views: 669

Answers (3)

rozina
rozina

Reputation: 4232

You can disable the warning for this function with a #pragma command, which depends on the compiler you are using. You will have to google that yourself.

Edit: since you mention you are using VisualStudio, here is a link to disable warnings. :)

Once you disable the warning you can add a static_assert to check if s1 and s2 are in range of the Num_Type. Although I find it strange that your compiler does not do that itself since everything is known at compile time.

template <typename Num_Type, int s1 = 2, int s2 = 3> void test1(Num_Type &n)
{    
    constexpr auto max = sizeof(Num_Type) * 8;
    static_assert(s1 < max && s2 < max, "integer overflow");

    // this is just an example code:
    int a = n >> s1,
        b = n << s2;
}

Live demo

Upvotes: 1

bolov
bolov

Reputation: 75696

I see no need for templates. All you need is simple overloading:

auto test(char n) { ... }
auto test(uint16_t n) { .. }
auto test(uint32_t n) { .. }

Upvotes: 0

aybassiouny
aybassiouny

Reputation: 578

The healthy way to change template function behavior depending on input type is to use template specialization. For example:

template <typename num_t> test(num_t n);
template <> test<int> (num_t n){
    int shift_amount = 4;
    // do shifts
}
template <> test<char> (num_t n){
    int shift_amount = 1;
    // do shifts
}

Also, make sure to surround your shifts with if checks to make sure there is no overflow.

Upvotes: 0

Related Questions