I've seen many example codes that use recursion to extract the values from a parameter pack. Is there any way, other than recursion, to extract the values from a parameter pack?
Asked
Active
Viewed 656 times
0
-
The first element would be the degenerate case of recursing once, which is identical to calling one function. Why is that a problem? Is calling a non-recursive function OK? – Useless Apr 26 '20 at 15:02
-
@Useless Because recursion is discouraged; it's compared to a chainsaw. – Sapphire_Brick Apr 27 '20 at 16:39
-
Discouraged by who? What is wrong with chainsaws? – Useless Apr 27 '20 at 22:55
-
@Useless see https://stackoverflow.com/questions/33511917/why-is-it-bad-to-call-functions-recursively – Sapphire_Brick Apr 28 '20 at 00:36
-
`std::get` very likely _is_ recursive, which is why I asked for clarification. It's OK because the depth is fixed, and everything is inlined and optimized away, at compile time. – Useless Apr 28 '20 at 21:51
-
@Useless Oh, I thought so too – Sapphire_Brick Apr 28 '20 at 22:02
-
1Recursion is risky when you don't know in advance how deep it can go (with the possible exception of tail-call recursion with a good optimizer). If it's limited, with a reasonable upper limit, _especially_ one known at compile time - it can be fine, and is pretty frequently used in a compile-time-only way with type packs and old-style typelists (which are themselves recursive). – Useless Apr 28 '20 at 22:07
3 Answers
1
Depending on what you want to do, you can use C++17 fold expressions:
template <int ... ints>
constexpr int product() {
return (ints * ...);
}

Aykhan Hagverdili
- 28,141
- 6
- 41
- 93
-
@Sapphire_Brick, no, it's not. Look up [recurion](https://en.wikipedia.org/wiki/Recursion) *"Recursion (adjective: recursive) occurs when a thing is defined in terms of **itself or of its type**"* – Aykhan Hagverdili Apr 28 '20 at 22:11
-
@Axyan I mean, it has the same disadvantages as recursion. (Stack limit, difficult to understand/debug, compiles to more assembly due to template parameters, etc) – Sapphire_Brick May 13 '20 at 01:42
-
-
@Axyan Are you sure that `std::foward` isn't implemented recursively? – Sapphire_Brick May 13 '20 at 16:48
-
@Sapphire_Brick `std::forward` is a conditional cast. It generates no executable code. Not a single byte. Thus, it's not recursive. You can look up how it's implemented in your standard library. – Aykhan Hagverdili May 13 '20 at 17:19
-
@Sapphire_Brick You can see implementation of `std::forward` for libstdc++ [here](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/move.h#L74) – Aykhan Hagverdili May 13 '20 at 17:26
-
I'm sorry if my question wasn't clear. You're right about the getting the first value, it is as simple as calling another function, but I wanted to extract all values. I was unclear. – Sapphire_Brick May 15 '20 at 16:27
-
Your question wasn't clear previously, I've updated my answer. See if that's better – Aykhan Hagverdili May 15 '20 at 17:31
-
-
@Sapphire_Brick I thought you'd appreciate the simplification. – Aykhan Hagverdili May 16 '20 at 05:43
-
@Sapphire_Brick Seems like I don't quite understand your question. Please un-accept the answer so I can delete it. – Aykhan Hagverdili May 17 '20 at 16:05
-
I was wondering if there's a way to iterate over the items in a parameter pack without recursion. Your answer is perfectly fine. – Sapphire_Brick May 17 '20 at 16:09
1
You can forward all pack parameters as a tuple, then call get<0>
:
template<class ... Args>
void foo(Args&& ... args) {
auto&& first = std::get<0>(std::forward_as_tuple(std::forward<Args>(args)...));
}

rafix07
- 20,001
- 3
- 20
- 33
1
It turns out that it there's a workaround. C++ parameter pack expansions can be used as for each loops:
#include <iostream>
template <int ... ints>
constexpr int product() {
int ret = 1;
auto _ = {
([&](int i) -> int {
ret *= i;
return i;
})(ints)...
};
return ret;
}
int main() {
std::cout << product<2, 6, 3>() << '\n';
return 0;
}
The problems are:
- the above code only works for non-type template parameter packs.
there is no break or continue
Edit
Apparently, it's legal to have a goto within a lambda within a parameter pack expansion. (I wasn't aware of this because Clang has a bug that restricts `goto` operands). Nevertheless, it's not a good idea, because it doesn't "clean up" before leaving the lambda.
Sapphire_Brick
- 1,560
- 12
- 26
-
Perhaps this helps if you want to pass non-type elements. You can use if as a continue. https://godbolt.org/z/CrCNiv – Aykhan Hagverdili May 17 '20 at 16:49