This is just an educational question, which could otherwise be avoided entirely by leveraging on tools such as range-v3.
Anyway, consider this example in which a variadic number of containers is passed to a function which returns a tuple of iterators:
#include <tuple>
#include <iostream>
#include <vector>
template <typename ...T>
auto begin(T&... containers) { return std::tuple( begin(containers)... ); }
int main() {
std::vector<int> a{1,2,3};
std::vector<long> b{1000,2000,3000};
auto bg = begin(a,b);
(void) bg;
return 0;
}
Quite a lot of code duplication will be produced by adding the functions for all the other iterator makers (std::[end, cbegin, cend, rbegin, rend]). Therefore I was looking for a way to forward the generic iterator maker function into my function. I managed to come up with this:
template <auto F, typename ...T>
auto make(T&... containers) { return std::tuple( F(containers)... ); }
// called as this:
auto bg = make<[](auto& c){return std::begin(c);}> (a,b);
...which is more general but comes with an horrendous syntax for the user, Ideally the call should be something like:
auto bg = make<std::begin>(a, b); // or
auto bg = make(std::begin, a, b);
but I have not been able to make these beauties work...