I want my function to be able to take array.begin() and array.end() as arguments. As far as I understand, the begin/end functions return a pointer to the first/last element of the array. Then why does the following code not work? How should I write the code instead?
#include <iostream>
#include <array>
template<class T> void foo(const T* begin, const T* end) {
...
}
int main() {
std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
foo(arr.begin(), arr.end()); // <-- error!
return 0;
}
>Solution :
As far as I understand, the begin/end functions return a pointer to the first/last element of the array
No. begin and end return iterators. The standard library works with iterators. Iterators are a generalization of pointers.
Iterators behave like pointers and you use them like pointers (e.g. *it to access the element), with some caveats: not all iterators have all the operations a pointer does. A pointer satisfies the random access iterator concept, so on some implementations the iterator of std::array could be just an alias for the pointer type, but you can’t rely on that. E.g. on the same compiler it can be a pointer for the release build, but a full class for the debug build.
The idiomatic way is to write:
template<class It>
void foo(It begin, It end) {
for (auto it = begin; it != end; ++it) {
const auto& elem = *it;
// ..
}
}
Since C++20 we should transition from iterator pairs to ranges:
void foo(std::ranges::range const auto& r) {
for (const auto& elem : r) {
// ...
}
}