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;
}
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.
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.
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.
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.
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.
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;
}
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With