Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiply variable number of arguments

Say I have a variable amount of arguments which I want to multiply together. The first way I think of is a recursive algorithm:

template<typename Head>
u64 Multiply(Head head) const
{
    return head;
}

template<typename Head, typename... Tail>
u64 Multiply(Head head, Tail... tail) const
{
    return head * Multiply(tail...);
}

But then I saw this trick:

// u32 and u64 are 32 and 64 bit unsigned integers.
template<typename... T>
u64 Multiply(T... args)
{
    u64 res = 1;
    for (const u32& arg: {args...})
        res *= arg;
    return res;
}

The second one appears way nicer to me. Easier to read. However, how does this act on performance? Is anything being copied? What does {args...} do in the first place? Is there a better method?

I have access to C++14.

Edit to be clear: It is about run time multiplication, not compile time.

More to be clear: I do not want to compute integers necessarily(although that is my current application), but the algorithm that I found was specialized for integers.

More: Arguments are of the same type. Algorithms without this restriction would be very interesting but maybe for a different question.

like image 215
Aart Stuurman Avatar asked Nov 27 '16 18:11

Aart Stuurman


People also ask

What is a variable number of arguments?

To call a function with a variable number of arguments, simply specify any number of arguments in the function call. An example is the printf function from the C run-time library. The function call must include one argument for each type name declared in the parameter list or the list of argument types.

How do you multiply parameters in Python?

Usually, when we multiply two variables, we use x×y, where x and y are variables. However, in most programming languages, including Python, we use the * (asterisk) sign to multiply variables instead of ×. So, to take the product of two variables, we use x*y.

Can a function have multiple arguments?

Some functions are designed to return values, while others are designed for other purposes. We pass arguments in a function, we can pass no arguments at all, single arguments or multiple arguments to a function and can call the function multiple times.


Video Answer


1 Answers

There are multiple questions asked here:

  1. What's the impact on performance? Dunno. You'll need to measure. Depending on the type of the arguments I can imagine that the compiler entirely optimizes things either way, though: it does know the number of arguments and the types.
  2. What is { args... }? Well, it creates an std::initializer_list<T> for the common type of the arguments (assuming there is one). You may want to use the value with std::common_type_t<T...> instead of a fixed type, though.
  3. Is there a better method? There are a couple of approaches although I could imagine that the compiler actually does rather well with this expansion. The alternative which immediately comes to mind is return (args * ... * 1); which, however, requires C++17. If there is at least one argument the * 1 can be omitted: it is there to avoid a compile-time error if there is an empty list of variadic parameters.
like image 91
Dietmar Kühl Avatar answered Oct 21 '22 07:10

Dietmar Kühl