dgorur
dgorur

Reputation: 1662

Binding a ref-qualified function with nanobind

What is the appropriate nanobind syntax to expose the instance method below?

struct Foo {
  int &value() & {
    return v;
  };
  int v;
};

With pybind, one could use static_cast with Foo::* syntax to cast the function pointer to the appropriate type, like so:

nb::class_<Foo>(m, "Foo").def("value", static_cast<int &(Foo::*)() &>(&Foo::value));

but with nanobind, I get this error:

...third_party/nanobind/include/nanobind/nb_class.h:567:28: error: no matching
function for call to 'cpp_function_def<Foo>(int& (Foo::*)() &, nanobind::scope,
nanobind::name, nanobind::is_method)'
    567 |         cpp_function_def<T>((detail::forward_t<Func>) f, scope(*this),
        |         ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    568 |                             name(name_), is_method(), extra...);
        |                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Do I need some sort of wrapper class with a non-ref-qualified method?

Upvotes: 0

Views: 74

Answers (1)

Kirisame Igna
Kirisame Igna

Reputation: 401

If you're comfortable about unspecified behaviors (which mostly means you can rely on it if you have tested it on your target platforms with your target toolchain), you can just use a reinterpret_cast, as the standard states:

A prvalue of type “pointer to member of X of type T1” can be explicitly converted to a prvalue of a different type “pointer to member of Y of type T2” if T1 and T2 are both function types or both object types. The null member pointer value ([conv.mem]) is converted to the null member pointer value of the destination type. The result of this conversion is unspecified, except in the following cases

nb::class_<Foo>(m, "Foo").def("value", reinterpret_cast<int &(Foo::*)()>(&Foo::value));

But I guess it is better to just implement it using a well-behaved lambda:

nb::class_<Foo>(m, "Foo").def("value", [](Foo* self) { return self->value(); });

It avoids the weird intricacies of casting in C++, and works just as fine.

Upvotes: 1

Related Questions