0

Is there a way to have the same template that can handle n (variable)-nested loops ?

for example :

for (auto & node : mnodes) {
    for (auto & parent : node->parents) {
        \\ do something
   }
}
for (auto & tree : mtrees) {
    for (auto & branch : tree->mbranches) {
         for(auto & root : branch ->roots  ) {
             \\ do something
       }
   }
}

The parameters of the outer and inner loops are always different and the number of the inner loops is different too.

Hazem Abaza
  • 331
  • 4
  • 21
  • 2
    please be more specific. What parameters you want to choose at compile time what at runtime? Is it always `parents`, `children` and `values` or different members? Btw the answer to "is there a way?" is always "yes". Did you try something? Can you show code that would illustrate what that template should look like or how you want to use it? – 463035818_is_not_an_ai Feb 26 '20 at 12:35
  • Do you want to recursively descend a nested templates or a tree of pointers. Two different things? One is (for example ) **std::vector>>** and the other is just a tree of nodes than can be explored using a tree traversal at runtime. – bradgonesurfing Feb 26 '20 at 12:35
  • C++20's coroutines or ranges might be helpful in that regard. Chaining transformation or selector functions. – Timo Feb 26 '20 at 12:37
  • I asked a question similar to this a while ago. The answers are instructive. https://stackoverflow.com/questions/59964594/is-it-possible-to-match-recursively-integer-template-parameters-in-c – bradgonesurfing Feb 26 '20 at 12:38
  • @bradgonesurfing I wanted a flexible template that can loop over variable depth/level of my arguments – Hazem Abaza Feb 26 '20 at 12:39
  • Probably this is what you are looking for https://stackoverflow.com/questions/34535795/n-dimensionally-nested-metaloops-with-templates/34601545 – Paul Feb 26 '20 at 12:40
  • @paul I had the same suggestion but my guess is that the OP is not actually asking for this. I think he has a normal tree structure and wants to do a depth first traversal. But he hasn't really given enough info. – bradgonesurfing Feb 26 '20 at 12:41
  • 1
    @HazemAbaza Can you please provide the full implementation of the classes you wish to iterate over. For example are children also nodes? So do children have their own children which have their own children. You need to show us the definitions and types. – bradgonesurfing Feb 26 '20 at 12:44
  • I need to extract some information from my class arguments in which i use many loops to extract them in my maps Every outer loop is different ( I edited the question ) and the number of inner loop is different from one argument to another – Hazem Abaza Feb 26 '20 at 12:45
  • "a flexible template that can loop over variable depth/level of my arguments" is going to be about as complex to call as just nesting the loops. What you may want to do is extract the common loop bodies into functions – Caleth Feb 26 '20 at 14:06

2 Answers2

1

You can take a variadic pack of function(-like)s, and loop over all but the last.

template <typename T, typename Last>
void nested_foreach(T&& t, Last&& last) {
     std::forward<Last>(last)(std::forward<T>(t));
}

template <typename T, typename First, typename Second, typename... Rest>
void nested_foreach(T & t, First&& first, Second&& second, Rest&& rest) {
    for (auto&& u : std::forward<First>(first)(std::forward<T>(t))) {
        nested_foreach(std::forward<decltype(u)>(u), std::forward<Second>(second), std::forward<Rest>(rest)...);
    }
}

Which you would use like:

nested_foreach(mnodes, std::mem_fn(&Node::parents), [](auto &){ /* do something */ });

nested_foreach(mtrees, std::mem_fn(&Tree::mbranches), std::mem_fn(&Branch::roots), [](auto &){ /* do something */ });
Caleth
  • 52,200
  • 2
  • 44
  • 75
0

I think a template approach is too complicated. I would move the variable logic in separated functions

void do_something_parents(const Node &node) {
    for (auto & parent : node->parents) {
        \\ do sthg
   }
}

void do_something_children(const Node &node) {
    for (auto & child : node->children) {
        for(auto & value : node ->values  ) {
         \\ do sthg
        }
    }
}

Then, you can use them as

for (auto & node : mnodes) {
    do_something_parents(node);
    do_something_children(node);
}
schorsch312
  • 5,553
  • 5
  • 28
  • 57
  • This won't work if the children are also nodes that have their own children and so on. However the OP hasn't really provided enough information. – bradgonesurfing Feb 26 '20 at 12:42