Piecewise initialisation of std::array

huangapple go评论69阅读模式
英文:

Piecewise initialisation of std::array

问题

如何编写一个std::array连接函数?

template <typename T, std::size_t sza, std::size_t szb>
std::array<T, sza+szb> concat (const std::array<T, sza>& aa, 
                                const std::array<T, szb>& ab)
{
    std::array<T, sza+szb> result;
    std::copy(std::begin(aa), std::end(aa), std::begin(result));
    std::copy(std::begin(ab), std::end(ab), std::begin(result) + sza);
    return result;
}

T不具备默认构造能力时,这当然是无法工作的。如何修复这个问题?

英文:

How can I write an std::array concatenation function?

template &lt;typename T, std::size_t sza, std::size_t szb&gt;
std::array&lt;T, sza+szb&gt; concat (const std::array&lt;T, sza&gt;&amp; aa, 
                                const std::array&lt;T, szb&gt;&amp; ab)
{
    std::array&lt;T, sza+szb&gt; result;
    std::copy(std::begin(aa), std::end(aa), std::begin(result));
    std::copy(std::begin(ab), std::end(ab), std::begin(result) + sza);
    return result;
}

This of course doesn't work when T is not default-constructible. How can this be fixed?

答案1

得分: 13

C++20 引入了像n. m.答案中展示的显式lambda模板参数列表。

C++14 的解决方案需要一个辅助函数:

template &lt;typename T, std::size_t... ai, std::size_t... bi&gt;
std::array&lt;T, sizeof...(ai) + sizeof...(bi)&gt;
concat_impl(std::array&lt;T, sizeof...(ai)&gt; const&amp; aa, 
            std::array&lt;T, sizeof...(bi)&gt; const&amp; ab,
            std::index_sequence&lt;ai...&gt;, std::index_sequence&lt;bi...&gt;)
{
    return std::array&lt;T, sizeof...(ai) + sizeof...(bi)&gt;{
      aa[ai]..., ab[bi]...
    };
};

template &lt;typename T, std::size_t sza, std::size_t szb&gt;
std::array&lt;T, sza + szb&gt; concat (std::array&lt;T, sza&gt; const&amp; aa, 
                                 std::array&lt;T, szb&gt; const&amp; ab)
{
    return concat_impl(aa, ab, 
                       std::make_index_sequence&lt;sza&gt;{},
                       std::make_index_sequence&lt;szb&gt;{});
}
英文:

Explicit template parameter list for lambdas, as shown in n. m.'s answer, were introduced in C++20.

A C++14 solution needs an helper function:

template &lt;typename T, std::size_t... ai, std::size_t... bi&gt;
std::array&lt;T, sizeof...(ai) + sizeof...(bi)&gt;
concat_impl(std::array&lt;T, sizeof...(ai)&gt; const&amp; aa, 
            std::array&lt;T, sizeof...(bi)&gt; const&amp; ab,
            std::index_sequence&lt;ai...&gt;, std::index_sequence&lt;bi...&gt;)
{
    return std::array&lt;T, sizeof...(ai) + sizeof...(bi)&gt;{
      aa[ai]..., ab[bi]...
    };
};

template &lt;typename T, std::size_t sza, std::size_t szb&gt;
std::array&lt;T, sza + szb&gt; concat (std::array&lt;T, sza&gt; const&amp; aa, 
                                 std::array&lt;T, szb&gt; const&amp; ab)
{
    return concat_impl(aa, ab, 
                       std::make_index_sequence&lt;sza&gt;{},
                       std::make_index_sequence&lt;szb&gt;{});
}

答案2

得分: 12

将参数转换为使用 std::index_sequence 和一个辅助 lambda 函数的参数包展开。

template <typename T, std::size_t sza, std::size_t szb>
std::array<T, sza+szb> concat (const std::array<T, sza>& aa, 
                               const std::array<T, szb>& ab)
{
    auto doit = [&](std::index_sequence<ai...>, std::index_sequence<bi...>)
    {
        return std::array<T, sza+szb>{aa[ai]..., ab[bi]...};
    };
    return doit(std::make_index_sequence<sza>{}, std::make_index_sequence<szb>{});
}
英文:

Convert the parameters to parameter-pack expansions with std::index_sequence and a helper lambda.

template &lt;typename T, std::size_t sza, std::size_t szb&gt;
std::array&lt;T, sza+szb&gt; concat (const std::array&lt;T, sza&gt;&amp; aa, 
                               const std::array&lt;T, szb&gt;&amp; ab)
{
    auto doit = [&amp;]&lt;std::size_t... ai, std::size_t... bi&gt;
        (std::index_sequence&lt;ai...&gt;, std::index_sequence&lt;bi...&gt;)
    {
        return std::array&lt;T, sza+szb&gt;{aa[ai]..., ab[bi]...};
    };
    return doit(std::make_index_sequence&lt;sza&gt;{}, std::make_index_sequence&lt;szb&gt;{});
}

答案3

得分: 6

使用std::tuple_catstd::apply的帮助,您可以

template <typename T, std::size_t sza, std::size_t szb>
std::array<T, sza+szb> concat(const std::array<T, sza>& aa, 
                              const std::array<T, szb>& ab)
{
  return std::apply([](auto... elems) { return std::array{elems...}; },
                    std::tuple_cat(aa, ab));
}
英文:

With the help of std::tuple_cat and std::apply, you can

template &lt;typename T, std::size_t sza, std::size_t szb&gt;
std::array&lt;T, sza+szb&gt; concat(const std::array&lt;T, sza&gt;&amp; aa, 
                              const std::array&lt;T, szb&gt;&amp; ab)
{
  return std::apply([](auto... elems) { return std::array{elems...}; },
                    std::tuple_cat(aa, ab));
}

huangapple
  • 本文由 发表于 2023年2月6日 15:57:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75358644.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定