How to intitlialize an array partially to some default value?

Viewed 186

I have an array (say for ex., unsigned int arr[1000]).

I want to intilialize the elements of an array like this ..

arr = {4, 10, 34, 45, 6, 67, UINT_MAX, UINT_MAX .. 994 times}

That is until I assign some value, I want default value in the array to be UINT_MAX.

Is there any way to do this ?

Of course for loop is always there, but apart from that any other way.

3 Answers

Please use a 2 stage approach. First, use an intializer list and then fill the rest with std::fill

#include <limits>
#include <algorithm>

constexpr size_t ArraySize = 1000U;

int main() {
    int arr[ArraySize] = { 4,10,34,45,6,67 };
    
    std::fill(arr + 6U, arr + ArraySize, std::numeric_limits<int>::max());

    return 0;
}

Use std::fill:

unsigned int array[5];
std::fill(array, array + 5, UINT_MAX);

or std::fill_n:

unsigned int array[5];
int count = 5; //           -   number of elements to modify
auto value = UINT_MAX; //   -   the value to be assigned 
std::fill_n(array, count, value);

Alternatively, consider using std::array instead. It is a thin wrapper over C-style arrays with some extras like iterators and size() functions. Also, it doesn't decay to a pointer automatically.

Expanding on @Evg's comment below, a more idiomatic, generic, safe and reliable way would be to use the functionality provided by the library:

unsigned int array[5];
// number of elements to modify
int count = std::size(array); // C++17

// the value to be assigned 
auto value = std::numeric_limits<uint32_t>::max();

std::fill_n(std::begin(array), count, value);

//OR with std::fill
std::fill(std::begin(array), std::end(array), value);

The advantages of the above approach are obvious:

  • You can just switch the container from a C-style array to a std::vector or std::array and you wouldn't have to change any other parts in the code above.
  • If you change the size of the array, the code will automatically adapt
  • Less chances for human error

The following allows you to do what you want to do with any type, size and default value:

template<typename T, size_t Size, size_t N, size_t... In, size_t... Isize>
constexpr std::array<T, Size> make_array_impl(const T(&user_supplied)[N], T default_value, std::index_sequence<In...>, std::index_sequence<Isize...>)
{
    return {user_supplied[In]..., (Isize, default_value)...};
}

template<typename T, size_t Size, size_t N>
constexpr std::array<T, Size> make_array(const T(&user_supplied)[N], T default_value)
{
    static_assert(N <= Size, "bla bla bla");
    return make_array_impl<T, Size> (user_supplied, default_value, std::make_index_sequence<N>{}, std::make_index_sequence<Size - N>{});
}

You can use it like this:

int main()
{
    auto arr = make_array<unsigned int, 1000>({4, 10, 34, 45, 6, 67}, UINT_MAX); // expands to arr = {4, 10, 34, 45, 6, 67, UINT_MAX... 994 times}
}

Try it on godbolt

Related