Pybind11: default arguments in constructors

Created on 21 Jul 2017  路  4Comments  路  Source: pybind/pybind11

This comment from a year ago suggests that pybind11 does not support default arguments in class constructors 脿 la

class Foo {
  public:
  Foo(
      const std::shared_ptr<bar> & poly,
      const std::array<double, 3> & direction,
      const double alpha = 0.0,
      const double edge_size = 0.0
      )
  {
  // [...]
  }

Is this information still up-to-date?

Most helpful comment

@jagerman, could pybind11 support default arguments for constructors without having to repeat the defaults, using something like this:

py::class_<Foo> c(m, "Foo");
c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
    py::optional<
        const double,
        const double
    >
>());

this would be shortcut for:

py::class_<Foo> c(m, "Foo");

c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
>());


c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
    const double
>());

c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
    const double,
    const double
>());

Note that Boost.Python supports this syntax.

All 4 comments

C++ default arguments are really syntactic sugar: that code only defines one constructor with 4 arguments; when you leave off the last one or two in a constructor, the compiler generates a construction call with the defaults added in.

So with that in mind, pybind can't know that there are default arguments there, it has to be told, which is what py::arg (or the _a annotation) are for:

http://pybind11.readthedocs.io/en/stable/basics.html#default-args

(Also note that defaults specified this way don't have to agree with the defaults specified in C++: that is, your python interface could have default values for mandatory C++ arguments or vice versa; the defaults given by py::arg can also be different than those specified by C++).

As to the original question: There's nothing special about constructors; py::arg defaults work the same there as they do for other methods.

Right on, that does the trick! I hadn't looked at py::init<...> like any other function before.

@jagerman, could pybind11 support default arguments for constructors without having to repeat the defaults, using something like this:

py::class_<Foo> c(m, "Foo");
c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
    py::optional<
        const double,
        const double
    >
>());

this would be shortcut for:

py::class_<Foo> c(m, "Foo");

c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
>());


c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
    const double
>());

c.def(py::init<
    const std::shared_ptr<bar>&,
    const std::array<double, 3>&,
    const double,
    const double
>());

Note that Boost.Python supports this syntax.

Was this page helpful?
0 / 5 - 0 ratings