How to fill std::array<int, N> N with the same constants during initialization?

  • Required during initialization, the native fill() method does not work? - PinkTux pm
  • @PinkTux a lot of methods, one initialization ... - doit
  • Sorry, I did not understand the profoundness of this comment :) Well, one initialization, and what? How does this fact prevent us from using the method? - PinkTux
  • @PinkTux in no way - doit

3 answers 3

With the help of relatively simple template magic, namely, using Variadic Templates (templates with a variable number of parameters), it is possible at the compilation stage to build an array containing the required number of identical elements.

 #include <array> #include <iostream> // Контейнер для массива. // numbers - список чисел для инициализации. template<int... numbers> struct Array { using array = std::array<int, sizeof...(numbers)>; static constexpr array data { { numbers... } }; }; // Генератор. // count - кол-во элементов. // fill - число, которым будет заполнен массив. template<unsigned count, int fill, int... numbers> struct Generator : Generator<count - 1, fill, fill, numbers...> { }; // Реализация, останавливающая рекурсию. template<int fill, int... numbers> struct Generator<0, fill, numbers...> { using Data = Array<numbers...>; }; // Проверка. int main() { const unsigned N = 10; auto a = Generator<N, 42>::Data::data; for (int i : a) std::cout << i << " "; } 
  • Hmm, my decision turned out to be your copy. Delete. - VladD
  • For the idea of ​​course a plus, but I wanted a little refactoring and formatting. Get rid of horizontal scrolling (for example, template and struct split apart in different lines), eliminate confusion with N and data , add auto some places, make make-function returning Generator<N, 111>::data::data; . - αλεχολυτ
  • @alexolut Frankly, lazy. Translated the answer to the general. - user194374

std::arra<int,3> x{ 2,2,2 }; :)

Unless to write his own, like

 using namespace std; template<typename T, int N> class array_v: public array<T,N> { public: array_v(T x) { fill(x); } }; template<typename T, int N> void out(const array<T,N>& a) { for(auto x: a) cout << x << " "; cout << endl; } int main () { array_v<int,100> a(5); out(a); } 
  • and if there are 100 elements? - doit
  • Write 100 numbers. Or write a derived class with a constructor calling fill . there is no such constructor that you need in this class ... - Harry
  • fill may not work in a script if the data can / should go into ROM. - VladD
  • @Harry sad, I thought you could use it - doit
  • @VladD I'm afraid that initialization in braces will not help in this case either. - Harry

If this is necessary in runtime, then we simply write an auxiliary function:

 template<std::size_t N> auto array_of_ints(int value) { std::array<int, N> a; a.fill(value); return a; } 

If the filled std::array needed at the compilation stage, then everything is a bit more complicated. In the current standard, std::array no constexpr functions, so you have to use the initialization list. To get the initialization list of the desired size, you can unpack the std::index_sequence :

 template<std::size_t... I> constexpr auto array_of_ints_impl(int value, std::index_sequence<I...>) { return std::array<int, sizeof...(I)>{((void)I, value)...}; } template<std::size_t N> constexpr auto array_of_ints(int value) { return array_of_ints_impl(value, std::make_index_sequence<N>{}); } 

Here {((void)I, value)...} turns into {value, ..., value} , castes (void)I need to suppress the compiler warning.

Check: http://coliru.stacked-crooked.com/a/a7e823996011ef39