Overloading

Introduction

Things get a little bit complex, when you have to export overloaded functions. In general the solution is to explicitly say to compiler what function you want to export, by specifying its type. Before we proceed, please take a look on the following class:

struct X
{
    bool f(int a)
    {
        return true;
    }

    bool f(int a, double b)
    {
        return true;
    }

    bool f(int a, double b, char c)
    {
        return true;
    }
};

This class has been taken from Boost.Python tutorials.

There are few approaches, which you can use in order to export the functions.

Do nothing approach

I am sure you will like “do nothing” approach. Py++ recognize that you want to export an overloaded function and will generate the right code:

namespace bp = boost::python;

BOOST_PYTHON_MODULE(pyplusplus){
  bp::class_< X >( "X" )
      .def(
          "f"
          , (bool ( ::X::* )( int ) )( &::X::f )
          , ( bp::arg("a") ) )
      .def(
          "f"
          , (bool ( ::X::* )( int,double ) )( &::X::f )
          , ( bp::arg("a"), bp::arg("b") ) )
      .def(
          "f"
          , (bool ( ::X::* )( int,double,char ) )( &::X::f )
          , ( bp::arg("a"), bp::arg("b"), bp::arg("c") ) );
}

“create_with_signature” approach

Well, while previous approach is very attractive it does not work in all cases and have a weakness.

Overloaded template function

I am sure you already know the following fact, but still I want to remind it:

  • CastXML doesn’t report about un-instantiated templates

It is very important to understand it. Lets take a look on the following source code:

struct Y{

    void do_smth( int );

    template< class T>
    void do_smth( T t );

};

If you didn’t instantiate( use ) do_smth member function, than CastXML will not report it. As a result, Py++ will not be aware of the fact that do_smth is an overloaded function. To make the long story short, the generated code will not compile. You have to instruct Py++ to generate code, which contains function type:

from pyplusplus import module_builder

mb = module_builder.module_builder_t( ... )
y = mb.class_( 'Y' )
y.member_function( 'do_smth' ).create_with_signature = True
#------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Every Py++ class, which describes C++ function\operator has create_with_signature property. You have to set it to True. Default value of the property is computed. If the exported function is overloaded, then its value is True otherwise it will be False.

Do nothing approach weakness

Code modification - the weakness of the “do nothing” approach. We live in the dynamic world. You can create bindings for a project, but a month letter, the project developers will add a new function to the exported class. Lets assume that the new function will introduce overloading. If create_with_signature has False as a value, than the previously generated code will not compile and you will have to run code generator one more time.

Consider to explicitly set create_with_signature to True. It will save your and your users time in future.

mb = module_builder_t( ... )
mb.calldefs().create_with_signature = True

Overloading using macros

Boost.Python provides two macros, which help you to deal with overloaded functions:

  • BOOST_PYTHON_FUNCTION_OVERLOADS
  • BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS

Boost.Python tutorials contain an explanation about this macros.

You can instruct Py++ to generate code, which will use the macros:

import module_builder

mb = module_builder.module_builder_t( ... )
x = mb.class_( "X" )
x.member_functions( "f" ).use_overload_macro = True
#-------------------------^^^^^^^^^^^^^^^^^^^^^^^^^

Member and free functions declaration classes have use_overload_macro property. The default value of the property is False.

You don’t really have to use the macros, unless you have “registration order” problem. The problem and work around described in default arguments document.