Reputation: 1898
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:
How can I customize bit-shift operations without getting "undefined behavior" warnings? or
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
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;
}
Upvotes: 1
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
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