Search code examples
c++vector

Extraction of data from arbitrary dimension nested vectors C++


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++?


Solution

  • 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