Using the same name to denote different objects in a single scope.
Using the same name in two different scopes is not overloading, and has no problems.
The functions must be distinguishable by their type signature which is the number and types of their arguments, not their names.
Operator overloading is a special case of function overloading, where the operator is used as the function name: e.g. + is used for addition of integers, reals, and strings.
Arrays, Lists, and Trees are general data structures that should be able to store any type of data.
Dynamic polymorphism and memory allocation is required if the data type is not known at compile time or if it is possible to store multiple types of data in the same data structure.
However, static polymorphism is more efficient, and preferred if the data type is known at compile time or if the data structure can only store one type of data, such that the implementation can be optimized for that type.
Generics is a way to achieve static polymorphism by allowing the programmer to define a template of a subprogram and then to create instances of the template for several types.
C does not support generics, but it can be achieved using void pointers and sizeof, although it is not type safe.
The generic functionality (template) must be copied for each type.
The generic parameters are compile-time parameters and are used by the compiler to generate the correct code for the instance.
The parameters form a contract between the code of the generic procedure and the instantiation.
C++ supports generics using templates, while Ada uses generics, and both are static polymorphism.