Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we iterate through an array passed to a function using for-each loop?

I know we can iterate through an array passed as an argument in this way:

// NO ERROR
void fun(int *a, int n){
    for(int i=0; i<n; i++)
        cout<<a[i];
}

But, is there any way I could iterate through an array using a for-each loop inside a function like this?

// ERROR
void fun(int *a, int n){
    for(auto x:a)
        cout<<x;
}
like image 483
sky_walker18 Avatar asked Mar 05 '21 11:03

sky_walker18


People also ask

Can you iterate array by using for each loop How?

Iterate array-like objects using forEach In order to iterate over its items, you have to call indirectly forEach() using the call() . The forEach() method is taken from Array.

Can an array be used in a for loop?

We can use iteration with a for loop to visit each element of an array. This is called traversing the array. Just start the index at 0 and loop while the index is less than the length of the array.


5 Answers

A pointer is not an array. If you pass a pointer to the first element of an array to a function then its no longer an array, but a pointer.

You can use a range based loop when you pass the array by reference:

#include <iostream>

template <size_t N>
void foo(int (&x)[N]) {
    for (int i : x) std::cout << i << " ";
}

int main() {
    int x[] = {1,2,3};
    foo(x);
}

Output:

1 2 3 

This works, because the range based loop uses std::begin(x) and std::end(x) to get iterators to the begin and end of the array. Pointers don't have a begin or end.

like image 86
463035818_is_not_a_number Avatar answered Oct 18 '22 21:10

463035818_is_not_a_number


In C++20, you can use std::span:

#include <cstddef>
#include <cstdio>
#include <span>

void foo(int* arr, std::size_t sz) {
  std::span<int> span{arr, sz};
  for (int elm : span) {
    std::printf("%d\n", elm);
  }
}

Or you could make span the input argument in the first place:

void foo(std::span<int> span) {
  for (int elm : span) {
    std::printf("%d\n", elm);
  }
}

If the signature of the function is flexible, I suggest you use the second option.

Pre C++20, here is an implementation of span from GSL. Or make your own wrapper class with begin() and end() functions.

like image 35
Ayxan Haqverdili Avatar answered Oct 18 '22 21:10

Ayxan Haqverdili


Alternative non-template C++20 solution:

auto range = std::views::counted(arr, sz);
for (auto elm : range) {

The benefit of this compared to std::span is that this is more general and works with any iterator, not requiring a contiguous iterator such as a pointer.

The benefit of using std::span instead of this is that you can use std::span as the function parameter without making it a template.


Alternative template solution (works pre C++20):

template <class Range>
void foo(const Range& range) {
    for (auto elm : range) {

The benefit of this compared to int (&arr)[N] is that it is much more general. This template works with all ranges.


Besides range-for, you could consider avoiding the loop entirely (works pre C++20):

auto print = [](auto elm) {
    std::cout << elm;
}
std::for_each_n(arr, sz, print);

I recommend this if you don't have C++20, cannot have boost / ranges / GSL libraries for some reason, and cannot have a template.

like image 43
eerorika Avatar answered Oct 18 '22 21:10

eerorika


yes, you can. Just pass the array by reference to a template function:

#include <iostream>
using namespace std;
 
template <size_t N> void foo(int (&arr)[N])
{
    for (auto i:arr)
        cout << i << " ";
}
 
int main()
{
    int array[] = { 5, 17, 3452, 546546, 756756, 75675, 756753, 345, 53};
    foo(array);
    return 0;
}
like image 31
mch Avatar answered Oct 18 '22 23:10

mch


And the real answer:

int made[] = {10 , 2 ,15};
 std::for_each(std::begin(made),std::end(made),[=](auto x){ std::cout << x << std::endl; });

You can parallelize std::for_each with say std::execution::par.

With function code will be:

#include <iostream>
#include <vector>
#include <execution>

void f(int (&made)[3])
{
     std::for_each(std::begin(made),std::end(made),[=](auto x){ std::cout << "and then " << x << std::endl; });
}

int main(int argc , char *argv[])
{

    int made[] = {10 , 2 ,15};
    f(made);
}
like image 40
Алексей Неудачин Avatar answered Oct 18 '22 23:10

Алексей Неудачин