A reference to the very good solution is given in comments by @Oberon.
But I think there are many different solutions to this problem. Here is my solution:
#include <tuple>
#include <type_traits>
template <class TestFunction, class... Containers, class... Types>
typename std::enable_if<sizeof...(Containers) == sizeof...(Types)>::type
TestNextLevel
(
TestFunction testFunction,
const std::tuple<Containers...>& containersTuple,
const Types&... parameters
)
{
testFunction(parameters...);
}
template <class TestFunction, class... Containers, class... Types>
typename std::enable_if<(sizeof...(Containers) > sizeof...(Types))>::type
TestNextLevel
(
TestFunction testFunction,
const std::tuple<Containers...>& containersTuple,
const Types&... parameters
)
{
for (const auto& element : std::get<sizeof...(Types)>(containersTuple))
{
TestNextLevel(testFunction, containersTuple, parameters..., element);
}
}
template <class TestFunction, class... Containers>
void TestAllCases
(
TestFunction testFunction,
const Containers&... containers
)
{
TestNextLevel
(
testFunction,
std::tuple<const Containers&...>(containers...)
);
}
Example of using:
TestAllCases(tester_func, vec_p1, vec_p2, vec_p3);