Search code examples
c++templatesrecursionvariadic-templatestemplate-specialization

Recursive template explanation C++


template<typename... ArgTypes>
int add(ArgTypes... args);

template<typename T, typename... ArgTypes>
int add(T t, ArgTypes... args)
{
    int sum = 0;
    return t + add(args...);
}
template<> int add() {
    return 0;
} 

How to add more operations like multiplication and subtraction? What does template<> int add() mean?

Could anyone explain in detail how this recursive template works?

UPD: Thank you guys regarding subtraction, yes, subtraction is not commutative so it's not really suitable for such recursive templating.

UPD2: Added a call stack as a reference for community Call Stack for variadic templates


Solution

  • It is quite common recursive variadic template. The idea is that we use recursion

    f(x0, x1, ..., xn) = f(f(x0, x1, ..., xn-1), xn) (1),

    in your sample

    add(x0, x1, ..., xn) = add(x0, x1, ..., xn-1) + xn.

    Variadic templates provides simple and useful way to create such a structure.

    First, define the general signature of the template (without implementation, becouse we never use general form)

    template<typename... ArgTypes>
    int add(ArgTypes... args);
    

    Now specialize template fuction for case with at least one parameter. We use recursion which extract first argument and calls itself recursively with reduced by one the number of parameters.

    template<typename T, typename... ArgTypes>
    int add(T t, ArgTypes... args)
    {
        int sum = 0;
        return t + add(args...); // recursive call without first arg
    }
    

    To stop recursion, we use template specialization for empty template parameters list (we add 0 at the last step).

    template<> int add() {
        return 0;
    } 
    

    For multiplication you need just change + by *, becuse general recursive form (1) is identical in both case, and change return 0 to return 1 (multiply by 1 at the last step).

    In the substraction case the general form of the recursion (1) is unusable, because a-b != b-a, ambiguity arises. Also with division and other noncommutative operations. You will have to clarify operations order.