Home > database >  Variadic template function
Variadic template function

Time:09-27

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;
}

Demo

  • Related