John Smith
John Smith

Reputation: 495

Iterator or std::iota with regular C++ Array?

Is there a way to achieve the same effect as this,

std::list<int> l(10);
std::iota(l.begin(), l.end(), -4);

With a regular int a[]?

Or, is the following the only way around:

for (iterator itr = begin; itr != end; ++itr)
    /* ... visit *itr here ... */

Upvotes: 0

Views: 1803

Answers (2)

einpoklum
einpoklum

Reputation: 132108

tl;dr: Wrap your array in a "span".

@idclev463035818's answer is the most straightforward thing to do. However, if you want to treat your array as a standard-library container in multiple contexts, consider wrapping the raw array in a span, like so:

auto a_ = std::span{a};

spans are lightweight reference-types to contiguous storage. They don't own their data, so you're not copying the array or anything. You can read more about spans here:

What is a "span" and when should I use one?

Anyway, now you can write:

std::iota(a_.begin(), a_.end(), -4);
for(x : a_) { do_stuff_with(x); }
auto c = std::ranges::count_if(a_, [](auto x) { return x > 3; });

and so on. Perhaps more importantly, the array "decays" into a pointer if you pass it to another function, and then you can no longer use std::begin() and std::end() on it; the span can be passed around, so it's more robust.

However - std::span is only in the standard beginning with C++20. Before that you can use the span implementation in the gsl-lite library, for example.

Upvotes: 3

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123114

C++11 added std::begin and std::end. Since then there is no difference:

std::list<int> l(10);
std::iota(std::begin(l),std::end(l), -4);
int a[10];
std::iota(std::begin(a),std::end(a), -4);

Upvotes: 7

Related Questions