Skip to content

Latest commit

 

History

History
132 lines (100 loc) · 3 KB

316.md

File metadata and controls

132 lines (100 loc) · 3 KB
Info

Example

static_assert(0 == std::rank_v<void>);
static_assert(0 == std::rank_v<int>);
static_assert(1 == std::rank_v<int[]>);
static_assert(0 == std::rank_v<int[0]>);
static_assert(1 == std::rank_v<int[1]>);
static_assert(1 == std::rank_v<int[42]>);
static_assert(2 == std::rank_v<int[][2]>);
static_assert(2 == std::rank_v<int[1][2]>);
static_assert(3 == std::rank_v<int[1][2][3]>);

https://godbolt.org/z/e657s3

Puzzle

Can you implement standard compliant version of std::rank_v?

static_assert(0 == rank_v<void>);
static_assert(0 == rank_v<int>);
static_assert(1 == rank_v<int[]>);
static_assert(0 == rank_v<int[0]>);
static_assert(1 == rank_v<int[1]>);
static_assert(1 == rank_v<int[42]>);
static_assert(2 == rank_v<int[][2]>);
static_assert(2 == rank_v<int[1][2]>);
static_assert(3 == rank_v<int[1][2][3]>);

https://godbolt.org/z/7Ms3W4TdP

Solutions

#include <type_traits>

template<class T>
struct prev;

template<class T, int N>
struct prev<T[N]> : std::type_identity<T> {};

template<class T>
struct prev<T[]> : std::type_identity<T> {};

template<class T>
constexpr auto return_rank()
{
    if constexpr (::std::is_array_v<T>) {
        return return_rank<typename prev<T>::type>() + 1;
    }
    return 0;
}

template<class T>
constexpr auto rank_v = return_rank<T>();

https://godbolt.org/z/qdx7bxde7

namespace detail {
template <typename T>
constexpr auto rank(){
    if constexpr (std::is_array_v<T>) {
        return 1 + rank<std::remove_extent_t<T>>();
    } else {
        return 0;
    }
}
};

template <typename T>
constexpr auto rank_v = detail::rank<T>();

https://godbolt.org/z/c88aheerd

template<class T>
struct rank : public std::integral_constant<std::size_t, 0> {};

template<class T>
struct rank<T[]> : public std::integral_constant<std::size_t, rank<T>::value + 1> {};

template<class T, std::size_t N>
struct rank<T[N]> : public std::integral_constant<std::size_t, rank<T>::value + 1> {};

template< class T >
inline constexpr std::size_t rank_v = rank<T>::value;

https://godbolt.org/z/YYdTesPKx

template <class>
constexpr auto rank_v = 0uz;

template <class T>
constexpr auto rank_v<T[]> = rank_v<T> + 1uz;

template <class T, auto N>
constexpr auto rank_v<T[N]> = rank_v<T[]>;

https://godbolt.org/z/G75xEEGfz

template<typename T>
constexpr auto rank_v = []{
  constexpr auto recur = []<typename U>(auto recur, std::type_identity<U>, auto accum){
    if constexpr (std::is_array_v<U>){
      return recur(recur, std::type_identity<std::remove_extent_t<U>>{}, accum+1);
    } else {
      return accum;
    }
  };
  return recur(recur, std::type_identity<T>{}, 0);
}();

https://godbolt.org/z/5eE1MWbj9