连接一系列std :: arrays

Dan*_*nra 10 c++ arrays templates c++11

请考虑以下事项:(Wandbox)

#include <array>
#include <algorithm>
#include <iostream>

template<typename T, int N, int M>
auto concat(const std::array<T, N>& ar1, const std::array<T, M>& ar2)
{
    std::array<T, N+M> result;
    std::copy (ar1.cbegin(), ar1.cend(), result.begin());
    std::copy (ar2.cbegin(), ar2.cend(), result.begin() + N);
    return result;
}

int main()
{
    std::array<int, 3> ar1 = {1, 2, 3};
    std::array<int, 2> ar2 = {4, 5};
    auto result = concat<int, 3, 2>(ar1, ar2);
    for (auto& x : result)
        std::cout << x << " ";
    std::cout << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

给定一个,, ... 的序列std::array<T, length1>,我如何推广上面的代码并编写一个将序列连接成一个函数的函数?std::array<T, length2>std::array<T, lengthK>std::array<T, sum(lengths)>

如果有一种方法可以编写一个可重用的函数,使用给定的二进制操作减少类似的模板类序列,例如,concat在上面的例子中使用,而不是编写一个特殊的方法(必须重新编写),这将是很好的.每次二进制op改变时写入).

(IIUC,相关的标准库算法(accumulate,reduce)仅适用于二进制操作的结果类始终相同的情况.)

Jar*_*d42 7

您可以执行以下操作:

template <typename F, typename T, typename T2>
auto func(F f, T&& t, T2&& t2)
{
    return f(std::forward<T>(t), std::forward<T2>(t2));
}

template <typename F, typename T, typename T2, typename ... Ts>
auto func(F f, T&& t, T2&& t2, Ts&&...args)
{
    return func(f, f(std::forward<T>(t), std::forward<T2>(t2)), std::forward<Ts>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

随着使用

struct concatenater
{
    template<typename T, std::size_t N, std::size_t M>
    auto operator()(const std::array<T, N>& ar1, const std::array<T, M>& ar2) const
    {
        std::array<T, N+M> result;
        std::copy (ar1.cbegin(), ar1.cend(), result.begin());
        std::copy (ar2.cbegin(), ar2.cend(), result.begin() + N);
        return result;
    }
};
Run Code Online (Sandbox Code Playgroud)

auto result = func(concatenater{}, ar1, ar2, ar3, ar4);
Run Code Online (Sandbox Code Playgroud)

演示


Vit*_*meo 6

给定一系列的std::array<T, length1>,, std::array<T, length2>...,std::array<T, lengthK>我怎样才能编写一个将序列连接成一个函数的函数std::array<T, sum(lengths)>

这是一个C++ 17解决方案.它很可能会缩短和改进,正在努力.

template <std::size_t Last = 0, typename TF, typename TArray, typename... TRest>
constexpr auto with_acc_sizes(TF&& f, const TArray& array, const TRest&... rest)
{
    f(array, std::integral_constant<std::size_t, Last>{});

    if constexpr(sizeof...(TRest) != 0)
    {
        with_acc_sizes<Last + std::tuple_size_v<TArray>>(f, rest...); 
    }
}

template<typename T, std::size_t... Sizes>
constexpr auto concat(const std::array<T, Sizes>&... arrays)
{
    std::array<T, (Sizes + ...)> result{};

    with_acc_sizes([&](const auto& arr, auto offset)
    {
        std::copy(arr.begin(), arr.end(), result.begin() + offset);
    }, arrays...);

    return result;
}
Run Code Online (Sandbox Code Playgroud)

用法:

std::array<int, 3> ar1 = {1, 2, 3};
std::array<int, 2> ar2 = {4, 5};
std::array<int, 3> ar3 = {6, 7, 8};
auto result = concat(ar1, ar2, ar3);
Run Code Online (Sandbox Code Playgroud)

直播wandbox示例

适用于g ++ 7clang ++ 5.

  • 这是我的.随意使用任何部分:http://melpon.org/wandbox/permlink/arkvF7HpZGr4LKOa.我没有使用`std :: copy`的唯一原因是保持它`constexpr`,因为这看起来很合适. (2认同)

Con*_*tor 6

这是一个通过折叠表达式的简单 C++17 解决方案:

#include <array>
#include <algorithm>

template <typename Type, std::size_t... sizes>
auto concatenate(const std::array<Type, sizes>&... arrays)
{
    std::array<Type, (sizes + ...)> result;
    std::size_t index{};

    ((std::copy_n(arrays.begin(), sizes, result.begin() + index), index += sizes), ...);

    return result;
}
Run Code Online (Sandbox Code Playgroud)

使用示例:

const std::array<int, 3> array1 = {{1, 2, 3}};
const std::array<int, 2> array2 = {{4, 5}};
const std::array<int, 4> array3 = {{6, 7, 8, 9}};

const auto result = concatenate(array1, array2, array3);
Run Code Online (Sandbox Code Playgroud)

Live demo