std::array
is implemented as a struct
holding a C-style fixed-length array as its sole data member. The begin()
iterator is usually a raw pointer to the 1st element of the array 1.
1: @bitmask makes a good point in comments: "Note that std::array<T,N>::iterator
does not have to be a raw-pointer. It usually is, but doesn't HAVE to be. Nor does it have to be convertible to a T*
. So your code is invalid C++ and compiles because of an implementation detail of your compiler.*"
The address of the 1st element of an array is guaranteed to be the same address as the array itself. And the address of the 1st member of a struct is guaranteed to be the same address as the struct itself. So, in theory, provided that the begin
iterator is really a raw pointer to the 1st array element, then you should be able to type-cast begin
to a std::array*
pointer - but only if you know at compile-time the EXACT template parameter values that were used to instantiate that std::array
, eg:
void xyz(int* begin, int* end) {
using array_type = array<int, 5>; // OK
array_type *arr = reinterpret_cast<array_type*>(begin);
...
}
int main() {
array<int, 5> x = {1, 2, 3, 4, 5};
xyz(x.begin(), x.end());
}
However, this will fail miserably if you can't guarantee that begin
comes only from a std::array
, and is a raw pointer to its 1st element.
And while you can determine the necessary T
template parameter from the type of the iterators begin passed in, you cannot determine the necessary N
template parameter using just iterators. That value must be a compile-time constant, but getting the distance between the 2 iterators can only be determined at runtime instead:
void xyz(int* begin, int* end) {
using array_type = array<int, ???>; // <-- can't use (end-begin) here!!!
array_type *arr = reinterpret_cast<array_type*>(begin);
...
}
Or:
template<typename Iter>
void xyz(Iter begin, Iter end) {
using array_type = array<iterator_traits<Iter>::value_type, ???>; // <-- can't use (end-begin) here!!!
array_type *arr = reinterpret_cast<array_type*>(begin);
...
}
The whole point of using iterators as function parameters in the first place is to abstract away the container type so it is not known or needed. So, it is very difficult, if not impossible, to determine the original container type from information gleamed from its iterators.
So, in this situation, if you really need access to the std::array
then you are best off simply passing the whole std::array
itself, not its iterators:
template<typename T, size_t N>
void xyz(array<T, N> &arr) {
...
}
int main() {
array<int, 5> x = {1, 2, 3, 4, 5};
xyz(x);
}