c++boost.gif (8819 bytes)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:

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