20.4 Overloading functions
As described in the reference manual function overloading is permitted in Stan, beginning in version 2.29.
This means multiple functions can be defined with the same name as long as they accept different numbers or types of arguments. User-defined functions can also overload Stan library functions.
20.4.1 Warning on usage
Overloading is a powerful productivity tool in programming languages, but it can also lead to confusion. In particular, it can be unclear at first glance which version of a function is being called at any particular call site, especially with type promotion allowed between scalar types. Because of this, it is a programming best practice that overloaded functions maintain the same meaning across definitions.
For example, consider a function triple
which has the following three
signatures
real triple(real x);
complex triple(complex x);
array[] real triple(array[] real);
One should expect that all overloads of this function perform the same basic task. This should lead to definitions of these functions which would satisfy the following assumptions that someone reading the program would expect
// The function does what it says
3.0) == 9.0
triple(// It is defined reasonably for different types
3.0)) == to_complex(triple(3.0))
triple(to_complex(// A container version of this function works by element
3.0, 4.0})[0] == triple({3.0, 4.0}[0]) triple({
Note that none of these properties are enforced by Stan, they are mentioned merely to warn against uses of overloading which cause confusion.
20.4.2 Function resolution
Stan resolves overloaded functions by the number and type of arguments passed to the function. This can be subtle when multiple signatures with the same number of arguments are present.
Consider the following function signatures
real foo(int a, real b);
real foo(real a, real b);
Given these, the function call foo(1.5, 2.5)
is unambiguous - it must resolve
to the second signature.
But, the function call foo(1, 1.5)
could be valid for either under Stan’s
promotion rules, which allow integers to be promoted to real numbers.
To resolve this, Stan selects the signature which requires the fewest number of
promotions for a given function call. In the above case, this means
the call foo(1, 1.5)
would select the first signature, because it requires 0
promotions (the second signature would require 1 promotion).
Furthermore, there must be only one such signature, e.g., the minimum number of promotions must be a unique minimum. This requirement forbids certain kinds of overloading. For example, consider the function signatures
real bar(int x, real y);
real bar(real x, int y);
These signatures do not have a unique minimum number of promotions for the call
bar(1, 2)
. Both signatures require one int
to real
promotion, and so it
cannot be determined which is correct. Stan will produce a compilation error in
this case.
Promotion from integers to complex numbers is considered to be two
separate promotions, first from int
to real
, then from real
to complex
. This
means that integer arguments will “prefer” a signature with real types over
complex types.
For example, consider the function signatures
real pop(real x);
real pop(complex x);
Stan will select the first signature when pop
is called with an integer
argument such as pop(0)
.