Paul Jurczak
Paul Jurczak

Reputation: 8173

Looking for a shortcut of list-initialization with consecutive integers

I have a bunch of longish hand initialized arrays, e.g.:

const std::array<int, 16> a{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
const std::array<int, 16> b{16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
...

Is there a way for a more concise initialization, e.g. along these lines (illegal):

const std::array<int, 16> a{std::views::iota(0, 16)};
const std::array<int, 16> b{std::views::iota(16, 32)};
...

Upvotes: 6

Views: 239

Answers (3)

Ajinkya Kamat
Ajinkya Kamat

Reputation: 345

You can do this using plain old iota. Like so,

#include <array>
#include <numeric>

template<typename T, std::size_t N>
constexpr auto make_range_array(T const & start) noexcept {
    std::array<T, N> range;
    std::iota(range.begin(), range.end(), start);
    return range;
}

auto main() -> int
{
    auto const a = make_range_array<int, 16>(0);
    auto const b = make_range_array<int, 16>(16);

}

Upvotes: 8

Jarod42
Jarod42

Reputation: 218138

With std::index_sequence, you might do something like:

template <std::size_t N>
constexpr std::array<int, N> make_iota_array(int start = 0)
{
    return [&]<std::size_t... Is>(std::index_sequence<Is...>){
        return std::array<int, N>{static_cast<int>(start + N)...};
    }(std::make_index_sequence<N>());
}

Upvotes: 5

Alan
Alan

Reputation: 1

Is there a way for a more concise initialization

Yes there is. You can write a helper make_array as shown below.

#include <iostream>
#include <type_traits>
#include <array>

template<std::size_t start, std::size_t end>
std::enable_if_t<(end > start), std::array<int, end - start>> constexpr make_array()
{
    std::array<int, end - start> tempArray{};
    std::size_t count = 0;
    for(int &elem:tempArray)
    {
        elem = start + count;
        count++;
    }
    return tempArray;
}

int main()
{
    constexpr auto arr = make_array<16, 32>();
}

Demo

Upvotes: 2

Related Questions