问题描述
我正在尝试使用 Pybind11 包装一些 C++ 类。
类 (Alpha) 有两个 getter,一个返回对成员 force_
的常量引用,另一个返回非常量引用。
struct Dummy {
double x{3.3};
};
class Alpha {
const Dummy& force() const {return force_;}
Dummy& force() {return force_;}
private:
Dummy force_;
};
我最初尝试使用 py::return_value_policy
但是这样,似乎我没有正确地消除两个版本的函数 force()
之间的歧义,因为我得到
note: template argument deduction/substitution Failed:
和 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","returns copy",py::return_value_policy::copy);
}
我是否正朝着完全错误的方向前进?我真的不想改变代码的 C++ 端。一个附带问题是:我怎么能明确地写出 &Alpha::force
来表示常量或非常量版本。
解决方法
我不知道 pybind,但我想 Func
是 def
试图从它的第二个参数推断的类型。问题是您无法获得指向重载集的函数指针。您只能获得指向单个函数的函数指针。
文档说明 Func 可以是普通的 C++ 函数、函数指针或 lambda 函数
好的,但它不能是一整套重载!
这就是为什么对于您的课程(我必须公开 force
!),这不会出于同样的原因:
int main() {
auto x = &Alpha::force;
}
产生的错误是:
<source>:15:10: error: variable 'x' with type 'auto' has incompatible initializer of type '<overloaded function type>'
auto x = &Alpha::force;
^ ~~~~~~~~~~~~~
无法仅从 &Alpha::force
推断类型。
您可以通过 static_cast
从重载集中选择一个:
auto x = static_cast< const Dummy& (Alpha::*)() const>(&Alpha::force);
非常量类似:
auto y = static_cast< Dummy& (Alpha::*)()>(&Alpha::force);
PS:您在文档中的引用实际上没有提到成员函数。我想那是由于报价不完整。如果 def
不能接受成员函数指针,您必须将 force
设为静态,或者将调用包装在自由函数 / lambda 中。不要忘记,指向成员函数的指针与指向自由函数的指针有着根本的不同(它们需要一个对象才能被调用)。