Jonathon Hill
Jonathon Hill

Reputation: 1057

Iterate over first N elements of c++11 std::array

I am using a std::array (c++11). I am choosing to use a std::array because I want the size to be fixed at compile time (as opposed to runtime). Is there anyway I can iterate over the first N elements ONLY. i.e. something like:

std::array<int,6> myArray = {0,0,0,0,0,0};
std::find_if(myArray.begin(), myArray.begin() + 4, [](int x){return (x%2==1);});

This is not the best example because find_if returns an iterator marking the FIRST odd number, but you get the idea (I only want to consider the first N, in this case N=4, elements of my std::array).

Note: There are questions similar to this one, but the answer always involves using a different container (vector or valarray, which is not what I want. As I described early, I want to size of the container to be fixed at compile time).

Thank you in advance!!

Upvotes: 6

Views: 8531

Answers (3)

pjb
pjb

Reputation: 91

With C++20, a std::span can be used to create a subset view of a std::array much like std::string_view does for std::string. The span replaces maintaining the variable 'N' for the number of sub-elements.

auto part = std::span(myArray).first(4);

std::find_if(part.begin(), part.end(), [](int x) {return (x % 2 == 1); });

A std::span offers many other benefits. It can be used in range based for loops. And by using std::span.subspan, a span can view any range of elements, not limited to just the first N. A span can also be used not just with std::array, but also with C arrays, std::vector, and other contiguous containers.

Upvotes: 0

DevSolar
DevSolar

Reputation: 70263

From the way you presented your question, I assume that you say "iterate over", but actually mean "operate on with an algorithm".

The behaviour is not specific to a container, but to the iterator type of the container.

std::array::iterator_type satisfies RandomAccessIterator, the same as std::vector and std::deque.

That means that, given

std::array<int,6> myArray = {0,0,0,0,0,0};

and

auto end = myArray.begin() // ...

you can add a number n to it...

auto end = myArray.begin() + 4;

...resulting in an iterator to one element beyond the nth element in the array. As that is the very definition for an end iterator for the sequence,

std::find_if(myArray.begin(), myArray.begin() + 4, ... )

works just fine. A somewhat more intuitive example:

#include <algorithm>
#include <array>
#include <iostream>

#define N 4

int main()
{
    std::array<char, 6> myArray = { 'a', 'b', 'c', 'd', 'e', 'f' };
    auto end = myArray.begin() + N;
    if ( std::find( myArray.begin(), end, 'd' ) != end )
    {
        std::cout << "Found.\n";
    }
    return 0;
}

This finds the 4th element in the array, and prints "Found."

Change #define N 4 to #define N 3, and it prints nothing.

Of course, this is assuming that your array has N elements. If you aren't sure, check N <= myArray.size() first and use myArray.end() instead if required.


For completeness:

  • A BidirectionalIterator (list, set, multiset, map, multimap) only supports ++ and --.
  • A ForwardIterator (forward_list, unordered_set, unordered_multiset, unordered_map, unordered_multimap) only supports ++.
  • An InputIterator does not support dereferencing the result of postfix ++.

Upvotes: 3

user1781434
user1781434

Reputation:

If you want to iterate over the first N numbers of a std::array, just do something like:

#include <iostream>
#include <array>

int main() {
    constexpr const int N = 4;
    std::array<int, 6> arr{ 0, 1, 2, 3, 4, 5 };
    for (auto it = std::begin(arr); it != std::begin(arr) + N && it != std::end(arr); ++it)
        std::cout << *it << std::endl;
}

Upvotes: 0

Related Questions