Default Arguments

Boost.Python wraps (member) function pointers. Unfortunately, C++ function pointers carry no default argument info. Take a function f with default arguments:

    int f(int, double = 3.14, char const* = "hello");

But the type of a pointer to the function f has no information about its default arguments:

    int(*g)(int,double,char const*) = f;    // defaults lost!

When we pass this function pointer to the def function, there is no way to retrieve the default arguments:

    def("f", f);                            // defaults lost!

Because of this, when wrapping C++ code in earlier versions of Boost.Python, we had to resort to writing thin wrappers:

    // write "thin wrappers"
    int f1(int x) { f(x); }
    int f2(int x, double y) { f(x,y); }

    /*...*/

        // in module init
        def("f", f);  // all arguments
        def("f", f2); // two arguments
        def("f", f1); // one argument

When you want to wrap functions (or member functions) that either:

Boost.Python now has a way to make it easier.

For instance, given a function:

    int foo(int a, char b = 1, unsigned c = 2, double d = 3);

The macro invocation:

    BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)

Will automatically create the thin wrappers for us. This macro will create a class foo_overloads that can be passed on to def(...). The third and fourth macro argument are the minimum arguments and maximum arguments, respectively. In our foo function the minimum number of arguments is 1 and the maximum number of arguments is 4. The def(...) function will automatically add all the foo variants for us:

    .def("foo", foo, foo_overloads());

A similar facility is provided for class constructors, again, with default arguments or a sequence of overloads. Remember init<...>? For example, given a class X with a constructor:

    struct X
    {
        X(int a, char b = 'D', std::string c = "constructor", double d = 0.0);
        /*...*/
    }

You can easily add this constructor to Boost.Python in one shot:

    .def(init<int, optional<char, std::string, double> >())

Notice the use of init<...> and optional<...> to signify the default (optional arguments).