# Function Overloading

## An Example

To expose overloaded functions in Python, simply `def()` each one with the same Python name:

>     inline int f1() { return 3; }
>     inline int f2(int x) { return x + 1; }

>     class X {
>     public:
>         X() : m_value(0) {}
>         X(int n) : m_value(n) {}
>         int value() const { return m_value; }
>         void value(int v) { m_value = v; }
>     private:
>         int m_value;
>     };
>       ...

>     BOOST_PYTHON_MODULE_INIT(overload_demo)
>     {
>         try
>         {
>             boost::python::module_builder overload_demo("overload_demo");
>             // Overloaded functions at module scope
>             overload_demo.def(f1, "f");
>             overload_demo.def(f2, "f");

>             boost::python::class_builder<X> x_class(overload_demo, "X");
>             // Overloaded constructors
>             x_class.def(boost::python::constructor<>());
>             x_class.def(boost::python::constructor<int>());

>             // Overloaded member functions
>             x_class.def((int (X::*)() const)&X::value, "value");
>             x_class.def((void (X::*)(int))&X::value, "value");
>       ...

Now in Python:

>     >>> from overload_demo import *
>     >>> x0 = X()
>     >>> x1 = X(1)
>     >>> x0.value()
>     0
>     >>> x1.value()
>     1
>     >>> x0.value(3)
>     >>> x0.value()
>     3
>     >>> X('hello')
>     TypeError: No overloaded functions match (X, string). Candidates are:
>     void (*)()
>     void (*)(int)
>     >>> f()
>     3
>     >>> f(4)
>     5

## Discussion

Notice that overloading in the Python module was produced three ways:

1. by combining the non-overloaded C++ functions `int f1()` and `int f2(int)` and exposing them as `f` in Python.
2. by exposing the overloaded constructors of `class X`
3. by exposing the overloaded member functions `X::value`.

Techniques 1. and 3. above are really alternatives. In case 3, you need to form a pointer to each of the overloaded functions. The casting syntax shown above is one way to do that in C++. Case 1 does not require complicated-looking casts, but may not be viable if you can't change your C++ interface. N.B. There's really nothing unsafe about casting an overloaded (member) function address this way: the compiler won't let you write it at all unless you get it right.

## An Alternative to Casting

This approach is not neccessarily better, but may be preferable for some people who have trouble writing out the types of (member) function pointers or simply prefer to avoid all casts as a matter of principle:

>     // Forwarding functions for X::value
>     inline void set_x_value(X& self, int v) { self.value(v); }
>     inline int get_x_value(X& self) { return self.value(); }
>        ...
>             // Overloaded member functions
>             x_class.def(set_x_value, "value");
>             x_class.def(get_x_value, "value");

Here we are taking advantage of the ability to expose C++ functions at namespace scope as Python member functions.

## Overload Resolution

The function overload resolution mechanism works as follows:

- Attribute lookup for extension classes proceeds in the usual Python way using a depth-first, left-to-right search. When a class is found which has a matching attribute, only functions overloaded in the context of that class are candidates for overload resolution. In this sense, overload resolution mirrors the C++ mechanism, where a name in a derived class ``hides'' all functions with the same name from a base class.

- Within a name-space context (extension class or module), overloaded functions are tried in the same order they were `def()`ed. The first function whose signature can be made to match each argument passed is the one which is ultimately called. This means in particular that you cannot overload the same function on both ```int`'' and ```float`'' because Python automatically converts either of the two types into the other one. If the ```float`'' overload is found first, it is used also used for arguments of type ```int`'' as well, and the ```int`'' version of the function is never invoked.

Next: Inheritance Previous: Overridable Virtual Functions Up: Top

© Copyright David Abrahams 2001. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided ``as is'' without express or implied warranty, and with no claim as to its suitability for any purpose.

Updated: Mar 6, 2001