c++ - 在编译时将两个或多个不同大小的数组合并为一个数组

标签 c++ arrays c++14

我无法找到关于如何在现代 C++ 的编译时组合两个或多个数组的答案。

#include <array>
#include <cstdint>

const std::array<std::uint8_t, 1> one_elem = {1};
const std::array<std::uint8_t, 2> two_elem = {2, 3};
const std::array<std::uint8_t, 3> all = {one_elem, two_elem}; 
// expected: all == {1, 2, 3}

我会很高兴任何有点容易阅读的东西,例如

std::uint8_t one_elem[] = {1};
std::uint8_t two_elem[] = {2, 3};
std::uint8_t all[] = {one_elem, two_elem}; // cannot be that hard

有办法吗?我该怎么做才能解决这个问题?

最佳答案

如果你使用的是 C++17,你可以这样做:

template <typename T, std::size_t N1, std::size_t N2>
constexpr std::array<T, N1 + N2> concat(std::array<T, N1> lhs, std::array<T, N2> rhs)
{
    std::array<T, N1 + N2> result{};
    std::size_t index = 0;

    for (auto& el : lhs) {
        result[index] = std::move(el);
        ++index;
    }
    for (auto& el : rhs) {
        result[index] = std::move(el);
        ++index;
    }

    return result;
}

constexpr std::array<std::uint8_t, 1> one_elem = {1};
constexpr std::array<std::uint8_t, 2> two_elem = {2, 3};
constexpr std::array<std::uint8_t, 3> all = concat(one_elem, two_elem);

它在 C++14 中不起作用,因为 std::array 在 C++17 之前不是 constexpr 友好的。但是,如果您不关心最终结果是 constexpr,您可以简单地将每个变量标记为 const,这样就可以了:

const std::array<std::uint8_t, 1> one_elem = {1};
const std::array<std::uint8_t, 2> two_elem = {2, 3};
const std::array<std::uint8_t, 3> all = concat(one_elem, two_elem);

编译器几乎肯定会优化 concat

如果您需要 C++14 解决方案,我们必须通过 std::array 的构造函数来创建它,所以它不是那么好:

#include <array>
#include <cstdint>
#include <cstddef>
#include <type_traits>

// We need to have two parameter packs in order to
// unpack both arrays. The easiest way I could think of for
// doing so is by using a parameter pack on a template class
template <std::size_t... I1s>
struct ConcatHelper
{
    template <typename T, std::size_t... I2s>
    static constexpr std::array<T, sizeof...(I1s) + sizeof...(I2s)>
    concat(std::array<T, sizeof...(I1s)> const& lhs,
           std::array<T, sizeof...(I2s)> const& rhs,
           std::index_sequence<I2s...>)
    {
        return { lhs[I1s]... , rhs[I2s]... };
    }
};

// Makes it easier to get the correct ConcatHelper if we know a
// std::index_sequence. There is no implementation for this function,
// since we are only getting its type via decltype()
template <std::size_t... I1s>
ConcatHelper<I1s...> get_helper_type(std::index_sequence<I1s...>);

template <typename T, std::size_t N1, std::size_t N2>
constexpr std::array<T, N1 + N2> concat(std::array<T, N1> const& lhs, std::array<T, N2> const& rhs)
{
    return decltype(get_helper_type(std::make_index_sequence<N1>{}))::concat(lhs, rhs, std::make_index_sequence<N2>{});
}

constexpr std::array<std::uint8_t, 1> one_elem = {1};
constexpr std::array<std::uint8_t, 2> two_elem = {2, 3};
constexpr std::array<std::uint8_t, 3> all = concat(one_elem, two_elem);

关于c++ - 在编译时将两个或多个不同大小的数组合并为一个数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45287195/

相关文章:

c++ - 构建模板类型的编译时列表?

c++ - 如何从两个数组中生成一对 vector ,然后使用 CUDA/Thrust 按该对的第一个元素排序?

c++ - 跨平台开发?

java - 数组中变量之间的距离

python - 从 3D 数组中删除与从 3D 数组中删除的行相对应的行

c++ - 泛型 lambda,实参类型推导(auto)

带有 std::enable_if 的 C++ 可变参数模板部分模板特化

c++ - 计算地址差异是未定义的行为吗?

c++ - 一个非常简单的c++ oop问题

ios - 在 swift 2.0 中解析 JSON 时出错