通过参数包从任意索引初始化 std::array

pla*_*cel 5 c++ templates variadic-templates c++11 c++14

std::array通过可变参数模板参数初始化一个,从给定的索引开始,可以通过以下方式完成:

#include <array>

template <typename T, size_t N>
struct A
{
   template <typename ... Ts>
   A(size_t i, Ts ... vals)
   {
      constexpr size_t P = sizeof...(vals);
      std::array<T, P> temp{ vals... };

      for (size_t j = 0; j < P; ++j)
      {
         arr[i + j] = temp[j];
      }
   }

   std::array<T, N> arr;
};
Run Code Online (Sandbox Code Playgroud)

但是是否可以在不将参数包转换为临时元组或另一个 std::array 的情况下实现相同的目标?

Jar*_*d42 3

您可以使用std::index_sequence和委托构造函数:

template <typename T, size_t N>
struct A
{
   template <typename ... Ts>
   A(size_t i, Ts&& ... vals)
   :
       A(std::index_sequence_for<Ts...>{}, i, std::forward<Ts>(vals)...)
   {}

   template <std::size_t...Is, typename ... Ts>
   A(std::index_sequence<Is...>, size_t i, Ts&& ... vals)
   {
      int dummy[] = {0, ((arr[i + Is] = vals), void(), 0)...};
      static_cast<void>(dummy); // Avoid warning for unused variable
   }

   std::array<T, N> arr;
};
Run Code Online (Sandbox Code Playgroud)

或者用C++17的Folding表达式,

   template <std::size_t...Is, typename ... Ts>
   A(std::index_sequence<Is...>, size_t i, Ts&& ... vals)
   {
      (static_cast<void>(arr[i + Is] = vals), ...);
   }
Run Code Online (Sandbox Code Playgroud)

  • @Yakk:使用 c++1z 的表达式折叠,可以删除虚拟数组:`((arr[i + Is] = vals), ...)`。 (2认同)