带参数包绑定重载模板

问题描述 投票:0回答:0

我正在使用

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)’
}
templates sfinae pybind11
© www.soinside.com 2019 - 2024. All rights reserved.