In C++ 11:
template<class T>
struct array_view {
T*b=nullptr;
T*e=nullptr;
T*begin()const{return b;}
T*end()const{return e;}
std::size_t size()const{return e-b;}
bool empty()const{return size()==0;}
T&operator[](std::size_t i)const{return b[i];}
};
which is a simple little class. Some helpers to make it:
template<class T>
array_view<T> view(T* b,T* e){return {b,e};}
template<class T>
array_view<T> view(T* b,std::size_t l){return {b,b+l};}
template<class T, unsigned N>
array_view<T> view(T(&a)[N]){return view(&a[0],N};}
template<class T, unsigned N>
array_view<T> view(std::array<T,N>& a){return view(&a[0],N};}
template<class T, unsigned N>
array_view<const T> view(std::array<T,N>const& a){return view(&a[0],N};}
template<class T, class...Xs>
array_view<T> view(std::vector<T,Xs...>& v){return view(v.data(),v.size()};}
template<class T, class...Xs>
array_view<const T> view(std::basic_string<T,Xs...>const & v){return view(v.data(),v.size()};}
template<class T, class...Xs>
array_view<T> view(std::vector<T,Xs...>& v){return view(v.data(),v.size()};}
template<class T, class...Xs>
array_view<const T> view(std::basic_string<T,Xs...>const & v){return view(v.data(),v.size()};}
and finally:
array_view<char> view(char*str){return view(str, strlen(str));}
array_view<char const> view(char const*str){return view(str, strlen(str));}
now we can do this:
for(char& c:view(str)){
// code
}
and get the index via &c-str
if we need it.
There is one more more efficient approach: use sentinals and pointer-to-index to avoid calculating the length prior to hitting the end.