I am trying to wrap some C++ class using Pybind11.
The class (Alpha) two getters, one returning a const reference to a member force_ the other one returning a non-const reference.
struct Dummy {
double x{3.3};
};
class Alpha {
const Dummy& force() const {return force_;}
Dummy& force() {return force_;}
private:
Dummy force_;
};
I initially tried using the py::return_value_policy however this way, it seems like i didn't correctly disambiguate between the two versions of function force() as I am getting
note: template argument deduction/substitution failed: and couldn’t deduce template parameter ‘Func’
py::class_<Alpha>(m, "Alpha")
.def(py::init())
.def("force", &Alpha::force, "returns reference", py::return_value_policy::reference_internal)
.def("force", &Alpha::force, "returns copy", py::return_value_policy::copy);
}
Am I heading in a completely wrong direction? I do not really want do alter the C++ side of the code. A side question would be: How could I write &Alpha::force unambiguously to either mean the const or non-const version.
I don't know pybind, but I suppose Func is the type that def tries to deduce from its second parameter. The issue is that you cannot get a function pointer to an overload set. You can only get a function pointer to a single function.
The documentation states that Func can be a plain C++ function, a function pointer, or a lambda function
Ok, but it cannot be a whole set of overloads!
Thats why with your class (I had to make force public!), this won't work for the same reason:
int main() {
auto x = &Alpha::force;
}
Resulting error is:
<source>:15:10: error: variable 'x' with type 'auto' has incompatible initializer of type '<overloaded function type>'
auto x = &Alpha::force;
^ ~~~~~~~~~~~~~
There is just no way to deduce the type from &Alpha::force alone.
You can pick one from the overload set via a static_cast:
auto x = static_cast< const Dummy& (Alpha::*)() const>(&Alpha::force);
Similar for the non-const:
auto y = static_cast< Dummy& (Alpha::*)()>(&Alpha::force);
PS: Your quote from the docs actually do not mention member functions. I suppose thats due to an incomplete quote. If def cannot accept member function pointers you would have to either make force static, or wrap the call in a free function / lambda. Don't forget that pointers to member functions are fundamentally different from pointers to free functions (they need an object to be called).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With