我想实现这个函数(一个可以连接任意数量数组的函数,并且它也考虑值类别):
template <typename ELEMENT, std::size_t ...SIZE>
constexpr auto concat(std::array<ELEMENT, SIZE> &&&...arrays) {
return std::array<ELEMENT, SUMMED_SIZE>{ CONCATENATED_ARRAY_ELEMENTS };
}
备注:
&&&
,我的意思是arrays
中的每个数组都可以是右值/左值引用(可以混合)SUMMED_SIZE
,是指SIZE的总和(这很简单)CONCATENATED_ARRAY_ELEMENTS
,是指每个arrays
数组的所有元素连接起来。如果 arrays
中的数组是右值/左值,则 CONCATENATED_ARRAY_ELEMENTS
中对应的元素也应该是右值/左值。arrays
中的每个元素进行一次移动/复制。ELEMENT
可能无法默认构造,因此元素必须通过复制/移动构造函数来构造。这可以吗?
对于两个数组实现这个函数并不难(godbolt),但我不知道如何将其推广到两个以上的数组。我可以手动编写 3/4/5/etc-argument 函数,但所需函数的数量呈指数级增长。
您可以使用 C++17 折叠表达式以避免递归解包。
我认为不可能按值类别复制或移动,因为完美转发在这里不适用,因此从函数内部,每个数组将被视为左值引用。
由于右值引用可以绑定到对
const
的左值引用,我建议通过 const std::array<int, Ns> & ...
获取参数,以便能够在调用中混合左值/右值引用作为参数。
这会导致如下所示的结果:
template <typename T, std::size_t ... Ns>
constexpr auto concat(const std::array<T, Ns> & ... arrays)
{
std::array<T, (Ns + ...)> result;
auto it = result.begin();
([&](){
std::copy_n(arrays.begin(), Ns, it);
it += Ns;
}(), ...);
return result;
}
当然,您可以仅使用右值引用为特定情况定义重载,以便通过移动替换副本:
template <typename T, std::size_t ... Ns>
constexpr auto concat(std::array<T, Ns> && ... arrays)
{
std::array<T, (Ns + ...)> result;
auto it = result.begin();
([&](){
std::copy_n(std::make_move_iterator(arrays.begin()), Ns, it);
it += Ns;
}(), ...);
return result;
}