c++ std::to_array用于多维数组

nom7f22z  于 2023-03-09  发布在  其他
关注(0)|答案(1)|浏览(172)

C++20增加了std::to_array,这样你就可以很容易地从C风格数组创建std::array,例如:

template<typename T, std::size_t N>
void foo(const T (&a)[N]) {
    auto arr = std::to_array(a);
}

但是,std::to_array不支持二维数组,因此以下命令将不起作用:

auto arr = to_array({1, 2}, {3, 4});

是否可以手动实施?

njthzxwz

njthzxwz1#

它是可以实现的,以下几种方法也可以:

constexpr auto a = to_array({1, 2}, {4, 5, 6});
// ^ std::array<std::array<int, 3>, 2>
constexpr auto b = to_array("nice", "thing");
// ^ std::array<std::array<char, 6>, 2>

下面是the code

template <typename T, std::size_t... N>
constexpr auto to_array(const T(&... arr)[N]) {
    constexpr size_t COLS = detail::max<N...>();
    return detail::to_2d_array_from_pack<sizeof...(N), COLS>(arr...);
}

使用以下帮助程序:

namespace detail {

template <std::size_t N1, std::size_t... Ns>
constexpr size_t max() {
    if constexpr(sizeof...(Ns) == 0) return N1;
    else {
        constexpr size_t max_rest = max<Ns...>();
        return N1 > max_rest ? N1: max_rest;
    }
}

template <std::size_t TargetSize, typename T, std::size_t N, std::size_t... I>
constexpr auto to_array(std::index_sequence<I...>, const T (&arr)[N]) {
    return std::array<T, TargetSize>{arr[I]...};
}

template <std::size_t TargetSize, typename T, std::size_t N>
constexpr auto to_array(const T(&arr)[N]) {
    return to_array<TargetSize>(std::make_index_sequence<N>{}, arr);
}

template <std::size_t TargetRows, std::size_t TargetCols, typename T, std::size_t... N>
constexpr auto to_2d_array_from_pack(const T(&... arr)[N]) {
    using TargetType = std::remove_cv_t<T>;
    return std::array<std::array<TargetType, TargetCols>, TargetRows> {to_array<TargetCols>(arr)...};
}

} // end of namespace detail

以上仅支持2D数组。要支持3D数组we can add

template <typename T, std::size_t... N, std::size_t... M>
constexpr auto to_array(const T(&... arr)[N][M]) {
    constexpr size_t Y_SIZE = detail::max<N...>();
    constexpr size_t Z_SIZE = detail::max<M...>();
    using TargetType = std::remove_cv_t<T>;
    return std::array<std::array<std::array<TargetType, Z_SIZE>, Y_SIZE>, sizeof...(N)> {
        detail::to_2d_array_from_array_of_arrays<Y_SIZE, Z_SIZE>(std::make_index_sequence<N>{}, arr)...
    };
}

使用名称空间detail中的以下帮助器:

template <std::size_t TargetRows, std::size_t TargetCols, typename T,
  std::size_t N, std::size_t M, std::size_t... I>
constexpr auto to_2d_array_from_array_of_arrays(std::index_sequence<I...>, const T (&arr)[N][M]) {
    return to_2d_array_from_pack<TargetRows, TargetCols>(arr[I]...);
}

相关问题