Tenho uma classe Color
que é um wrapper fino em torno de std::array
. Gostaria de poder usá-la de duas maneiras:
Color<5> color{1,2,3,4,5}
deve produzircolor.values = [1,2,3,4,5]
Color<5> color{3}
deve produzircolor.values = [3,3,3,3,3]
O que eu tenho atualmente é:
template <size_t N>
class Color {
public:
Color() = default;
Color(std::array<float, N> values) : values{ values } {};
template <IsNumeric... T>
Color(T... v) : values{ static_cast<float>(v)... } { };
....
private:
std::array<float, N> values;
}
Isso funciona corretamente para meu primeiro caso. No entanto, para o segundo caso, ele só produz: color.values = [3,0,0,0,0]
. Estou perdido sobre como fazer o segundo caso funcionar. Eu tentei:
template <size_t N>
class Color {
public:
Color() = default;
Color(std::array<float, N> values) : values{ values } {};
template <IsNumeric... T, typename std::enable_if<(sizeof...(T) == N), bool>::type = true>
Color(T... v) : values{ static_cast<float>(v)... } { };
template <IsNumeric T>
Color(T v) : values{ std::array<float, N>{ static_cast<float>(v) } } { };
...
}
Mas isso não muda nada.
Você pode fazer isso com a ajuda de
std::index_sequence
e uma função auxiliar. Como você já está usando conceitos, você deve usar umarequires
cláusula para substituirstd::enable_if
.Seu código não mostra qual
values
é o tipo do membro, mas o título da pergunta, assim como o outro construtor, parece implicar que é astd::array
e é isso que eu uso aqui. De qualquer forma, deve funcionar, desde que o tipo devalues
tenha um construtor variadic que faça a coisa correta.Isso pode ser verificado pela seguinte função principal de teste:
Demonstração: https://godbolt.org/z/KGeehW5x6
Você pode ter um único construtor usando uma função
fillpad
que preencherá até M itens no array (M sendo o número de itens na lista de inicialização).No caso de M<N, você pode completar o array com o último valor da lista.
Demonstração
Observe que se você quiser impor que 1 ou N argumentos sejam fornecidos, pode-se substituir o
static_assert
nafillpad
função por:Para tipos que precisam de "index_sequence" em sua interface, costumo colocá-lo como parâmetro de modelo:
Demonstração