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