Search code examples
c++11variadic-templatesoverloading

Variadic template function overloading


I have a class with a variadic template member function (foo) like below. The idea is to skip all doubles in the parameter and allocate an object with user provided arguments.

template <class T>
class Var {
public:

    template <typename U, typename ...Args>
    int foo(int index, Args... args)
    {
        T* p = new U(args...);
        // save in an array at index 'index'
    }

    template <typename U, typename ...Args>
    int foo (double index, Args... args)
    {
        // do something with index and skip it
        return foo<U>(args...);
    }
};

class A {
public:
    A (int i, const char *p)
    {

    }
};

int main ()
{
    Var<A> var;

    var.foo<A>(1.0, 2, 3, "Okay");
}

Now this works, there are 2 problem.

  • Enforce how many doubles to skip.Eg: skip 2 doubles and then the next argument should be an int. If it is not then throw error.

  • While at it, use 'int' in place of 'double'. So we will skip 2 ints. The next index will be a 'index' to an array.

Basically I want to pass the no. of ints to skip as class template parameter.

template <class T, int SKIP>
class Var {

And use SKIP to determine how many ints to skip.

Is it possible to do something like that?


Solution

  • So this is what I conjured up taking hint from Novelocrat. Just pasting it hear for the records.

    template <class T, int SKIP>
    class FooHelper {
    public:
    
        template <typename U, typename ...Args>
        static int foo_helper(int index, Args... args)
        {
            FooHelper<T, SKIP-1>::foo_helper<U>(args...);
            return 0;
        }
    };
    
    template <class T>
    class FooHelper<T, 0> {
    public:
    
        template <typename U, typename ...Args>
        static int foo_helper (Args... args)
        {
            auto p = new U(args...);
            return 0;
        }
    };
    
    template <class T, int SKIP>
    class Var {
    public:
    
        template <typename U, typename ...Args>
        int foo(Args ...args)
        {
            FooHelper<T, SKIP>::foo_helper<U>(args...);
            return 0;
        }
    };