Home > Software engineering >  A constexpr function that calculates how deep a std::vector is nested
A constexpr function that calculates how deep a std::vector is nested

Time:06-22

Is there a way to write a constexpr function that returns how deep a std::vector is nested?

Example:

get_vector_nested_layer_count<std::vector<std::vector<int>>>() // 2
get_vector_nested_layer_count<std::vector<std::vector<std::vector<float>>>>() // 3

CodePudding user response:

The easy way is to use recursion

#include <vector>

template<class T>
constexpr bool is_stl_vector = false;
template<class T, class Alloc>
constexpr bool is_stl_vector<std::vector<T, Alloc>> = true;

template<class T>
constexpr std::size_t get_vector_nested_layer_count() {
  if constexpr (is_stl_vector<T>)
    return 1   get_vector_nested_layer_count<typename T::value_type>();
  else
    return 0;
};

Demo

CodePudding user response:

Pre-C 17 (pre constexpr if) you can implement the underlying logic using a trait and specialization

#include <vector>

template <typename> struct vector_nested_layer_count {
  static constexpr int value{0};
};

template <typename T> struct vector_nested_layer_count<std::vector<T>> {
  static constexpr int value{1   vector_nested_layer_count<T>::value};
};

template <typename T>
constexpr int vector_nested_layer_count_v{vector_nested_layer_count<T>::value};

static_assert(vector_nested_layer_count_v<std::vector<std::vector<int>>> == 2);
static_assert(
    vector_nested_layer_count_v<std::vector<std::vector<std::vector<float>>>> ==
    3);

And if you're not happy with the idiomatic _v helper variable template (as opposed to a function) you can implement the function as:

template <typename T> constexpr int get_vector_nested_layer_count() {
  return vector_nested_layer_count_v<T>;
}

static_assert(get_vector_nested_layer_count<std::vector<std::vector<int>>>() ==
              2);
static_assert(get_vector_nested_layer_count<
                  std::vector<std::vector<std::vector<float>>>>() == 3);

If you're at C 17 or beyond the constexpr if approach of the other answer is arguably neater, if you really want a function API for this kind of query trait (somewhat atypical in classic meta-programming).

CodePudding user response:

you can also directly recurse on the count variable.

template<typename T>
constexpr auto count_nest_vector = 0;

template<typename T>
constexpr auto count_nest_vector<std::vector<T>> = 1 count_nest_vector<T>;

// not really need, but if you want a function.
template<typename T>
constexpr auto get_vector_nested_layer_count() {
    return count_nest_vector<T>;
};
  • Related