在编译时将两个或多个不同大小的数组合并为一个数组
Combine two or more arrays of different size to one array at compiletime
我无法找到如何在现代 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++中连接数组:std::tuple_cat
。唯一的问题是它为您提供了tuple<uint8_t, uint8_t, uint8_t>
而不是std::array<uint8_t, 3>
。但是这个问题可以用不同的标准库函数来解决:std::apply
。从技术上讲,这是C++17,但在C++14中可以实现。你只需要一个funject:
struct to_array_t {
template <class T, class... Ts>
std::array<std::decay_t<T>, sizeof...(Ts)+1> operator()(T&& t, Ts&&... ts) const {
return {{std::forward<T>(t), std::forward<Ts>(ts)...}};
}
} to_array{};
然后你可以使用它:
auto all = std::apply(to_array, std::tuple_cat(one_elem, two_elem));
隐藏在函数后面可能更容易:
template <class Target=void, class... TupleLike>
auto array_concat(TupleLike&&... tuples) {
return std::apply([](auto&& first, auto&&... rest){
using T = std::conditional_t<
!std::is_void<Target>::value, Target, std::decay_t<decltype(first)>>;
return std::array<T, sizeof...(rest)+1>{{
decltype(first)(first), decltype(rest)(rest)...
}};
}, std::tuple_cat(std::forward<TupleLike>(tuples)...));
}
使用lambdas的完美转发有点丑陋。Target
类型允许用户为生成的数组指定类型 - 否则,它将被选为第一个元素的衰减类型。
相关文章:
- 合并排序不排序自创建数组类 c++
- 数组为此合并排序函数提供了正确的输出,但向量给出了不正确的输出.出了什么问题?
- 我如何根据 c++ 中的行合并两个 2D 数组
- 使用基于数组的列表 c++ 合并 2 个数组
- 如何在 char 数组中合并两个数组以通过网络发送
- 合并数组的程序打印 0 而不是实际合并的数组
- 如果数组长度为 100000,则使用合并排序对反转进行计数会给出负数
- 合并两个数组后数组大小不正确
- 如何修复合并两个C++数组时'Invalid Pointer'
- 在OpenMP上的并行合并排序上的数组大小问题.如何将合并分类分类为更多任务
- C++全局常量数组:是否保证合并(优化)到一个副本中
- C - 为什么合并函数在递归调用后会逆转数组
- 合并排序 - 返回新数组,而不是将合并的数组复制到输入数组
- C MPI:STD ::在数组上合并
- 合并排序问题,在方法之间传递数组
- C 合并的数组输出错误
- 我如何在INT数组上实现合并排序
- C++将2个已排序的数组合并为1个已排序数组
- 将排序代码与数组合并,陷入合并,只需要一点点修正
- 将字符* 数组合并到uint16_t