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