消除非常量和常量访问方法的歧义 (Pybind11)

Disambiguate non-const and const access methods (Pybind11)

我正在尝试使用 Pybind11 包装一些 C++ class。 class (Alpha) 两个 getter,一个返回对成员的 const 引用 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", &Alpha::force, "returns copy", py::return_value_policy::copy);
}

我是不是走错了方向?我真的不想改变代码的 C++ 端。一个附带的问题是:我怎么能明确地写 &Alpha::force 来表示 const 或非 const 版本。

我不知道 pybind,但我想 Funcdef 试图从其第二个参数推导出来的类型。问题是您无法获得指向重载集的函数指针。您只能获取指向单个函数的函数指针。

The documentation states that Func can be a plain C++ function, a function pointer, or a lambda function

好的,但不能是一整套重载!

这就是为什么您的 class(我必须制作 force public!),出于同样的原因,这将不起作用:

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 中。不要忘记指向成员函数的指针与指向自由函数的指针有根本的不同(它们需要一个对象才能被调用)。