我正在使用
pybind11
在 Python 中使用 C++ 代码,我正在努力寻找绑定一些通用模板代码的最佳方法:
class MyBase {
public:
using Ptr = std::shared_ptr< MyBase >;
MyBase() = default;
virtual ~MyBase() = default;
/* ... */
};
class MyDerived {
public:
MyDerived() = default;
explicit MyDerived(double value0, double value1) { /* ... */ }
explicit MyDerived(size_t index) { /* ... */ }
/* ... */
};
class MyClass {
public:
MyClass() = default;
~MyClass() = default;
// non-templated overload
void foo(const MyBase::Ptr& arg) { /* ... */ }
// templated overloads
template < typename OtherClass, typename... Args, typename = typename std::enable_if< std::is_constructible< OtherClass, Args... >::value >::type,
typename = typename std::enable_if< std::is_base_of< MyBase, OtherClass >::value >::type >
void foo(Args&&... args) { /* ... */ }
template < typename OtherClass, typename... Args, typename = typename std::enable_if< std::is_constructible< OtherClass, Args... >::value >::type,
typename = typename std::enable_if< std::is_base_of< MyBase, OtherClass >::value >::type >
void foo(double value, Args&&... args) { /* ... */ }
};
声明 python 模块时,绑定模板化重载时出现错误,我怀疑这是由参数包和 SFINAE 函数引起的。此外,奇怪的是,
py::overload_cast
也不适用于非模板重载。
#include<memory>
#include<type_traits>
#include<pybind11/pybind11.h>
namespace py = pybind11;
using namespace py::literals;
PYBIND11_MODULE(pymylib, module) {
/* ... */
py::class_< MyBase >(module, "MyBase")
.def(py::init< >());
py::class_< MyDerived >(module, "MyDerived")
.def(py::init< double, double >(), "Constructs a new instance", "value0"_a, "value1l"_a)
.def(py::init< size_t >(), "Constructs a new instance", "index"_a);
// // bind non-templated function
// py::class_< MyClass >(module, "MyClass").def("foo", &MyClass::foo, "arg"_a); // error: no matching function for call to ‘pybind11::class_<motion::_bindings::MyClass>::def(const char [4], <unresolved overloaded function type>, pybind11::arg)’
py::class_< MyClass >(module, "MyClass").def("foo", static_cast< void (MyClass::*)(const MyBase::Ptr&) >(&MyClass::foo), "arg"_a); // OK!
// py::class_< MyClass >(module, "MyClass").def("foo", py::overload_cast< const MyBase::Ptr& >(&MyClass::foo), "arg"_a); // error: no match for call to ‘(const pybind11::detail::overload_cast_impl<const std::shared_ptr<motion::_bindings::MyBase>&>) (<unresolved overloaded function type>)’
// bind tempalted overload
// py::class_< MyClass >(module, "MyClass").def("foo", py::overload_cast< double, double >(&MyClass::foo< MyDerived, double, double >), "value0"_a, "value1"_a); // error: no match for call to ‘(const pybind11::detail::overload_cast_impl<double, double>) (<unresolved overloaded function type>)’
// py::class_< MyClass >(module, "MyClass").def("foo", static_cast< void (MyClass::*)(double, double) >(&MyClass::foo< MyDerived, double, double >), "value0"_a, "value1"_a); // error: no matches converting function ‘foo’ to type ‘void (class motion::_bindings::MyClass::*)(double, double)’
// py::class_< MyClass >(module, "MyClass").def("foo", static_cast< void (MyClass::*)(double, double) >(&MyClass::foo< MyDerived, double, double, std::true_type, std::true_type >), "value0"_a, "value1"_a); // error: no matches converting function ‘foo’ to type ‘void (class motion::_bindings::MyClass::*)(double, double)’
}