- when passing an array to a function by reference, does parameter not require explicit size information as in void my_func (const T &array) instead of void my_func (const T (&array)[10])?
A reference parameter does not necessarily have to be reference to an array.
const T & is a reference to a const T. If T type alias of int[10] for example, then const T & is const int (&)[10] i.e. reference to an array of 10 const int. If T is a template type parameter, then the template can be instantiated with different types, including array types of different sizes and also including non-array types.
const T (&)[10] is a reference to an array of 10 const T.
You don't need to pass size information separately when the size information is encoded in the type of the parameter, such as is the case when the parameter is a reference to an array.
But the example in my question neither defines alias
You're mistaken. Your example is a template function and a template type parameter is a type alias.
Function calling statement simply passes arr which is converted(decayed) into a pointer to int.
You're mistaken. arr does not decay to pointer to int when the reference is bound to it. Array decaying happens upon an lvalue to rvalue conversion. There is no such conversion when binding a reference to an object.
- what is the difference between a function having an array pointer paremeter void my_func (const T* array) and void my_func (const T(* array)[10])(with or without explicit array size) new version?
const T* is a pointer to const T.
const T(*)[10] is pointer to const T[10] i.e. pointer to an array of 10 T. For example, if T is an alias of int, then former is const int* and latter is const int(*)[10].
Note that if T is an array, then the former can also be a pointer to an array. For example if T is int[42], then former is const int(*)[42] i.e. a pointer to an array of 42 const int while the latter is const int(*)[42][10] i.e. pointer to an array of 10 arrays of 42 const int.
... and void my_func (const T* array[10])(with or without explicit array size) old version?
const T* array[10] is an array of 10 pointers to const T. However, a function parameter is never an array in C++. If a function is declared with an array parameter, that parameter is adjusted to be a pointer to element of such array. The element of an array of 10 pointers to const T is a pointer to const T i.e. const T* and a pointer to such object is const T**. As such, this parameter is actually const T**.
The difference between const T* and const T** is that latter is a pointer to the former.
If this works, then is the general template for any array size as below unnecessary?
It depends. If you don't need it, then it is unnecessary for your use case.
But that doesn't mean that it would be unnecessary altogether. For example, if you need a function overload that accepts only arrays, then you cannot use a T& parameter which can accept arguments that are not arrays.
why does template<typename _Ret, typename _Coll> requires 2 template arguments
Because the S in T (&arr)[S] has to be a template value parameter in order for the reference to be bound to arrays of any size. If you used a non-variable constant such as T (&arr)[10], then you could only accept arrays of one size.
but Sum<int64_t>(arr) specifies only 1 template argument?
This one doesn't use a reference to an array of S elements, so there is no need for a template value parameter S.
_Ret and _Coll names are reserved to the language implementation. By defining those names as template parameters, the behaviour of the program will be undefined. Do not define reserved names. You should choose other names for the template parameters.
std::spanmakes all of this go away. It's a cool function, though.arraydoesn't force the compiler to only accept array arguments and reject everything else.const T &array(whereTis a template parameter) can match a literal of typeint- which is undesirable if the function cannot do anything meaningful if the argument is not a collection. Whereasconst T (&array)[10]means the compiler will reject any argument that is not an array of10elements, whileconst T (&array)[S](whereSis a templated argument with integral type) is acceptable for an array of any size.