¿Cómo inicializar std :: array elegantemente si T no es construible por defecto?

¿Cómo inicializo std::array si T no es construible por defecto ?

Sé que es posible inicializarlo así:

 T t{args}; std::array a{t, t, t, t, t}; 

Pero n para mí es el parámetro de la plantilla:

 template void f(T value) { std::array items = ??? } 

E incluso si no era una plantilla, es bastante feo repetir el valor a mano si n es demasiado grande.

Dado N, podrías generar un tipo de secuencia llamado seq<0,1,2,3,...N-1> utilizando un generador llamado genseq_t<> , y luego haz esto:

 template void f(T value) { //genseq_t is seq<0,1,...N-1> std::array items = repeat(value, genseq_t{}); } 

donde repeat se define como:

 template auto repeat(T value, seq) -> std::array { //unpack N, repeating `value` sizeof...(N) times //note that (X, value) evaluates to value return {(N, value)...}; } 

Y el rest se define como:

 template struct seq { using type = seq; static const std::size_t size = sizeof ... (N); template struct push_back : seq {}; }; template struct genseq : genseq::type::template push_back {}; template<> struct genseq<0> : seq<> {}; template using genseq_t = typename genseq::type; 

Demo en línea

Espero que ayude.

Lamentablemente, las respuestas existentes aquí no funcionan para los tipos que no se pueden copiar. Entonces respondí a @Nawaz y lo modifiqué:

 #include  #include  template std::array repeat(std::index_sequence, Args &&... args) { return {{((void)Ix, T(args...))...}}; } template class initialized_array: public std::array { public: template initialized_array(Args &&... args) : std::array(repeat(std::make_index_sequence(), std::forward(args)...)) {} }; 

Tenga en cuenta que esta es una subclase std::array para que uno pueda escribir fácilmente

 class A { A(int, char) {} } ... class C { initialized_array data; ... C(): data(1, 'a') {} } 

Sin repetir el tipo y tamaño. Por supuesto, de esta manera también se puede implementar como una función initialize_array .

Lo siguiente resolverá su problema:

 #if 1 // Not in C++11, but in C++1y (with a non linear better version) template  struct index_sequence {}; template  struct make_index_sequence : make_index_sequence {}; template  struct make_index_sequence<0, Is...> : index_sequence {}; #endif namespace detail { template  constexpr std::array create_array(T value, index_sequence) { // cast Is to void to remove the warning: unused value return {{(static_cast(Is), value)...}}; } } template  constexpr std::array create_array(const T& value) { return detail::create_array(value, make_index_sequence()); } 

Así que pruébalo:

 struct NoDefaultConstructible { constexpr NoDefaultConstructible(int i) : m_i(i) { } int m_i; }; int main() { constexpr auto ar1 = create_array<10>(NoDefaultConstructible(42)); constexpr std::array ar2 = create_array<10>(NoDefaultConstructible(42)); return 0; }