Return the addition of variadic parameter pack
Asked Answered
B

1

6

Let's say I have a function sum that takes a variadic parameter pack.
This function needs to ADD UP all of the parameters of the parameter pack using the operator +.

NOTE: It CANNOT use the operator += in any way and can use only operator + (as the program CANNOT assume that all parameters have operator+= overloaded).

Then, function sum needs to return the whole "sum" or accumulative add-up.

Here is the basic structure of what it would look like:

template <class... Args>
auto sum(Args... args)
{
    // ... The code
}

NOTE: All arguments may not be of the same type AND you can assume that a corresponding overload of the operator+ exists for all types of the parameter pack.

It may be helpful to know that I am using C++ 20.

Biographer answered 17/7, 2023 at 4:45 Comment(6)
But operator+ could do lots of things. Matrices have a + and so do strings - what happens when you add a matrix to a string? Or are you saying that all the types passed to this function can be added to each other (like sometimes multiple matrices will be passed and sometimes multiple strings will be passed)?Thuja
@JerryJeremiah That was set in the intention that, if you had a class Foo and class Bar and overloaded the '+' operator to add instances of both, the function should allow you to. If you were to try to add something like a string and an int, for which an overload of the operator+ does not exist, that would just throw a compilation error, which is fine.Biographer
I think @JerryJeremiah is trying to say that + doesn't always mean sum, and you are not conveying that in any way. The language can't help much with that unfortunately, there are several ways to improve the quality of the code, 1) use a named concept in the class template <class... Arithmetic> auto sum( etc 2) do not imply semantic meaning in the function <class... Arithmetic> auto fold_plus( etc 3) do not name anything (use lambda) (see my answer).Nigro
@Nigro I should have clarified this earlier, but I did not intend for the + to represent a sum. I just named the function that as an example, but ultimately I should have just named it plus. It is not meant to be the sum or anything. It is just supposed to implement the + operator upon the parameters.Biographer
@Amolgorithm, yes, but it doesn't end there because there are at least two ways to do the fold if the operation is non-commutative or non-associative, to the left and right fold. In my answer I chose right_fold, but I should have asked which one you wanted to do. Of course, it is a bad idea to use + for noncommutative operations (like std::string does), but that is another story.Nigro
@JerryJeremiah, using decltype doesn't solve the conceptual semantic problem. It only adds SFINAE to your function, which you might or might not want.Nigro
N
9

Use C++17's fold expressions, https://en.cppreference.com/w/cpp/language/fold. You don't need to specify the return type in most cases.

#include<cassert>

template <class... Args>
auto sum(Args... args) {  // or right_fold_plus
    return (args + ...);
}

int main() {
    auto s = sum(1, 2, 3);
    assert( s == 1 + 2 + 3 );
}

https://godbolt.org/z/1Yh118ETb

NOTE: It is pretty much an accident of the language that one needs a function to do this, which, unfortunately, opens the opportunity to give the "wrong name" to a function (in the sense that it can do something that the name doesn't imply, like concatenating strings). In that sense, sum is not a good name because it could also be called concatenate. A more neutral name, without semantic implications, would be to call it right_fold_plus.

... or simply not give it a name it at all [](auto... xs) {return (xs + ...);}(1, 2, 3) (see https://godbolt.org/z/7x9PzrzY1)

Nigro answered 17/7, 2023 at 4:58 Comment(1)
+1 Thank you for the answer. I was expecting some sort of fold expression, I just wasn't sure how to implement it. So thanks for your answer.Biographer

© 2022 - 2024 — McMap. All rights reserved.