I want to scan through elements in an arbitrary number of nested vectors. I.e.
template <typename T>
void scan(std::vector<std::vector<...<std::vector<T>>...>> vecs)
{
for (int i = 0; i < vecs.size(); ++i)
for (int j = 0; j < vecs[i].size(); ++j)
...
for (int z = 0; z < vecs[i][j]...[w].size(); ++z)
vecs[i][j]...[w][z] = (T)0;
}
Somehow the function can do some depth-first search on the nested vectors. Is this even possible in C++?
You can make a helper type trait to detect if something is iterable. This is best done with std::void_t
as it basically can detect if an expression is valid:
template <typename, typename = void>
constexpr bool is_iterable = false;
template <typename T>
constexpr bool is_iterable<
T,
std::void_t< decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())
>
> = true;
And you can apply if constexpr
to easily make a recursive function that can choose whether to loop through or deal with a individual element.
template<typename T>
void scan(const T& o) {
if constexpr (is_iterable<T>) {
std::cout << "[";
for (const auto& elem : o) {
scan(elem);
}
std::cout << "]";
} else {
std::cout << o << " ";
}
}
This will work on any iterable object, including C-Arrays, std::vector, std::map, std::array, etc.
This is a C++17 solution, but this can be adapted easily to SFINAE if pre-C++17, or to concepts for C++20 and beyond.
I also made a small demo here: https://godbolt.org/z/chcY7dE3v