I have the following scenario:
class C
{
public:
template <typename T>
std::shared_ptr<T> foo();
std::shared_ptr<SomeClass> foo(std::string_view sw);
};
class DerivedFromC : public C
{
// no logic concerning foo
};
// in my bindings
pybind11::class_<DerivedFromC, ...some options...>(m, "Name")
.def("foo", pybind11::overload_cast<std::string_view>(&DerivedFromC::foo));
This code doesn't compile with an error message:
[build] pythonbind.hpp(51,21): error: no matching function for call to object of type 'const detail::overload_cast_impl<basic_string_view<char, char_traits<char>>>'
[build] 51 | .def("foo", pybind11::overload_cast<std::string_view>(&DerivedFromC::foo));
[build] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] ...\build\vcpkg_installed\x64-windows\include\pybind11/detail/common.h(1106,20): note: candidate template ignored: couldn't infer template argument 'Return'
[build] 1106 | constexpr auto operator()(Return (*pf)(Args...)) const noexcept -> decltype(pf) {
[build] | ^
[build] ...\build\vcpkg_installed\x64-windows\include\pybind11/detail/common.h(1111,20): note: candidate template ignored: couldn't infer template argument 'Return'
[build] 1111 | constexpr auto operator()(Return (Class::*pmf)(Args...), std::false_type = {}) const noexcept
[build] | ^
[build] ...\build\vcpkg_installed\x64-windows\include\pybind11/detail/common.h(1117,20): note: candidate function template not viable: requires 2 arguments, but 1 was provided
[build] 1117 | constexpr auto operator()(Return (Class::*pmf)(Args...) const, std::true_type) const noexcept
[build] | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Do I do something incorrect or is there a special way for retrieving the pointer of that function? For me, it feels like the overload_cast
function should have chosen the correct overload, as the templated one doesn't have any arguments.
I resolved my issue by manually static_cast
-ing to the correct signature like the following.
pybind11::class_<DerivedFromC, ...some options...>(m, "Name")
.def("foo", static_cast<std::shared_ptr<SomeClass>(DerivedFromC::*)(std::string_view)>(&DerivedFromC::foo));
However, this doesn't seem elegant to me. So, if anyone has a better (more elegant) solution, will take that one as an answer.