Эти две функции
void fun(int arr[]) {
cout << "arr[] called" << endl;
}
void fun(arrTen arr) {
cout << "arrTen called" << endl;
//cout << end(arr) - begin(arr) << endl;
}
имеют тот же тип, что и
void fun( int *arr);
, поскольку компилятор неявно корректирует параметр, имеющий тип массива, для указания указателя на тип элемента.
Таким образом, этот код нарушает правило единого определения.
Чтобы прояснить, рассмотрите эти объявления функций
void fun( int arr[100] );
void fun( int arr[10] );
void fun( int arr[1] );
void fun( int arr[] );
void fun( int *arr );
Все они объявляют одну и ту же функцию и все эти объявлениямогут быть включены в модуль компиляции, хотя они являются избыточными. Но у функции должно быть только одно определение.
С другой стороны, компилятор также не может выбирать между двумя функциями, которые принимают аргумент по ссылке или по значению.
Вы можете сделать одну функцию спостоянный параметр, такой как
void fun( const arrTen arr) {
cout << "arrTen called" << endl;
//cout << end(arr) - begin(arr) << endl;
}
В этом случае будет вызвана функция, которая принимает аргумент по ссылке.