I'm not sure if this is possible, but I would like to be able to recursively call a function based on the elements of a tuple. So for example a tuple such as std::tuple<int,float,double>
should call expand_nested
3 times, and in turn invoke it's callback function with a parameter of type either int
, float
or double
.
#include <tuple>
#include <vector>
#include <functional>
template <typename T>
struct tree_item
{
T param;
std::function<void(T)> callback;
};
template <typename... Ts>
struct tuple_node
{
std::tuple<Ts...> tupl;
};
// recursion base case
template <typename T>
void expand_nested(tree_item<T> ti)
{
ti.callback(ti.param);
}
// recursive function
template <typename T>
void expand_nested(tree_item<T> ti, tree_item<T> rest...)
{
ti.callback(ti.param);
expand_nested(ti, rest...);
}
template <typename... Ts>
void expand_root(tuple_node<Ts...> nodes)
{
auto current = std::get<1>(nodes.tupl);
auto rest = std::get<...>(nodes.tupl); // Made up syntax that doesn't work
// How can I fill the "rest" variable with the remaining elements of the "nodes.tupl" tuple?
expand_nested(current, rest...);
}
int main()
{
tuple_node<tree_item<int>, tree_item<float>> nodes;
tree_item<int> tree_int;
tree_item<float> tree_float;
tree_item<double> tree_double;
tuple_node<tree_item<int>, tree_item<float>, tree_item<double>> node;
node.tupl = std::make_tuple(tree_int, tree_float, tree_double);
expand_root(nodes);
}
Syntax for parameters pack in expand_nested
should be:
template <typename T, typename ... Rest>
void expand_nested(tree_item<T> ti, tree_item<Rest>... rest)
This
ti.callback(ti.param);
expand_nested(ti, rest...);
will give you infinite recursion (you are calling the same function with the same number of arguments of the first call), it should look like:
template <typename T, typename ... Rest>
void expand_nested(tree_item<T> ti, tree_item<Rest>... rest)
{
ti.callback(ti.param); // process ti
expand_nested(rest...); // don't pass ti, pass only the rest to further processing
}
Since C++17 there is easy way to extract all elements of tuple - use std::apply
:
template <typename... Ts>
void expand_root(tuple_node<Ts...> nodes)
{
std::apply([](auto&... tupleItems){
expand_nested(tupleItems...); }, nodes.tupl);
}