The best answer is to use a vector (which has a .size() method).
If you want to use basic C-style arrays instead, then we usually pass in the size as another parameter.
#include <iostream>
template <typename T, size_t N>
size_t ArrSize(T(&)[N]) { return N; }
void f(int *a, size_t size) {
for (size_t i = 0; i < size; ++i)
std::cout << a[i] << '\n';
}
// Could do it with a templated function, but it creates a new function for every differently sized array.
template <typename T, size_t N>
void g(T (&a)[N]) {
for (size_t i = 0; i < N; ++i)
std::cout << a[i] << '\n';
}
int main() {
int a[] = {1,2,3,4,5};
f(a, ArrSize(a));
g(a);
}