Como inicializar std :: array elegantemente se T não é padrão construtível?

Como faço para inicializar std::array se T não for construtível por padrão ?

Eu sei que é possível inicializá-lo assim:

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

Mas n para mim é o parâmetro do modelo:

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

E mesmo que não seja modelo, é muito feio repetir o valor à mão se n for muito grande.

Dado N, você poderia gerar um tipo de sequência chamado seq<0,1,2,3,...N-1> usando um gerador chamado genseq_t<> , então faça o seguinte:

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

onde repeat é definido 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)...}; } 

E o resto é definido 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; 

Demonstração online

Espero que ajude.

Infelizmente, as respostas existentes aqui não funcionam para tipos não copiáveis. Então eu peguei a resposta do @Nawaz e modifiquei:

 #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)...)) {} }; 

Note que esta é uma subclass std::array para que se possa escrever facilmente

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

Sem repetir o tipo e tamanho. Naturalmente, esse caminho também pode ser implementado como uma function initialize_array .

A seguir, você resolverá seu 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()); } 

Então teste:

 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; } 
Intereting Posts