I've got a custom class that has a tuple-like interface. Because I want my code to be as generic as possible, I thought that it would be a good idea to base my algorithms on the functions std::get
, std::tuple_size
, std::tuple_element
so you just have to specialize these functions to use my algorithms. Let's call the concept that requires these function specializations Tuple
.
Now I am trying to sum up the components of a Tuple
. The function declaration should be something like this:
template <class Tuple>
int sum_components(const Tuple& t);
I guess that there is a lot of template programming involved but I just can't figure out how to do it.
For the addition I would just use an overload of the global + operator
.
I am using c++1z.
With C++1z it's pretty simple with fold expressions. First, forward the tuple to an
_impl
function and provide it with index sequence to access all tuple elements, then sum:demo
A C++14 approach would be to recursively sum a variadic pack:
demo
A C++11 approach would be the C++14 approach with custom implementation of
index_sequence
. For example from here.As @ildjarn pointed out in the comments, the above examples are both employing right folds, while many programmers expect left folds in their code. The C++1z version is trivially changeable:
demo
And the C++14 isn't much worse, but there are more changes:
demo
This is very easy in c++17.
or
(...+e)
for the opposite fold direction.In previous versions, the right approach would be to write your own
apply
rather than writing a bespoke implementation. When your compiler updates, you can then delete code.In c++14, I might do this:
which is pretty close to
std::apply
in c++14. (I abusestd::ref
to getINVOKE
semantics). (It does not work perfectly with rvalue invokers, but that is very corner case).In c++11, I would advise upgrading your compiler at this point. In c++03 I'd advise upgrading your job at this point.
All of the above do right or left folds. In some cases, a binary tree fold might be better. This is trickier.
If your
+
does expression templates, the above code won't work well due to lifetime issues. You may have to add another template type for "afterwards, cast-to" to cause the temporary expression tree to evaluate in some cases.