I was trying to code a function that takes unbounded number of arguments in C . To do so, I had to try it in the function below.
With two arguments :
unsigned int bitClear(uint32_t &bitNum, unsigned int pos)
{
bitNum = bitNum & (~(1 << pos));
return bitNum;
}
But with unbounded number of arguments, I didn't want to use the cstdarg
from STL. Because, at each call, I have to give the number of arguments the function works with, followed by the arguments.
So, I was hoping to use variadic template function. I searched for solution here and there, but the answers I got from Stack Overflow did not really come close to what I was looking for. So, by looking at "C Templates The Complete Guide" on chapter 4 (Variadic Templates) I got some useful information.
// base case
template<typename T>
decltype(auto) bitClear(T &t, unsigned int pos)
{
t = t & (~(1 << pos));
return t;
}
// general case
template<typename T1, typename T2, typename... Args>
decltype(auto) bitClear(T1 &t1, T2 pos2, Args... args)
{
t1 = t1 & ~((1 << pos2)|(1 << bitSet(args...))); // recursive call
return t1;
}
This approach uses a recursive call to unpack the rest of the arguments in the function. Unfortunately, I did not get everything right though.
#include <iostream>
#include <bitset>
#define MAX 16
using namespace std;
// the template functions are defined here
int main(int argc, char** argv)
{
unsigned int u = 0b11111111111111; // the same as 0xFFFF;
cout << "Clearing multiple bits at once : " << bitset<MAX>(bitClear(u, 2, 5)) << "\n";
cout << "Clearing multiple bits at once : " << bitset<MAX>(bitClear(u, 2, 5, 10)) << "\n";
cout << "Clearing multiple bits at once : " << bitset<MAX>(bitClear(u, 2, 5, 7, 10, 11)) << "\n";
return 0;
}
The return :
Clearing multiple bits at once : 0011111111011011
Clearing multiple bits at once : 0011111111011011
Clearing multiple bits at once : 0011111111011011
Which is not correct, the expected result is :
Clearing multiple bits at once : 1111111111011011
Clearing multiple bits at once : 1111101111011011
Clearing multiple bits at once : 1111001101011011
After changing the above code by :
///** Base case **///
template<typename T>
decltype(auto) bitClear(T &par1)
{
return par1;
}
///**General case **///
template<typename T1, typename... Args>
decltype(auto) bitClear(T1 t1, Args... args)
{
t1 = t1 & ~(1 << bitClear(args...));
return t1;
}
I am unable to get the desired result and I can't even find where did I go wrong. Does anyone out there has any idea to help me overcome this hurdle?
CodePudding user response:
Something along these lines, perhaps:
template <typename Val, typename ... Pos>
Val& bitClear(Val& v, Pos... pos) {
((v &= ~(1 << pos)), ...);
return v;
}