Closed
Description
Required prerequisites
- Make sure you've read the documentation. Your issue may be addressed there.
- Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
- Consider asking first in the Gitter chat room or in a Discussion.
Problem description
In the following example the Struct
has a Python binding and is convertible on its own. Also std::unordered_set
works in general for build in types. However for the combination std::unordered_set<Struct>
the conversion fails at runtime with the error by calling test_func()
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: Unable to convert function return value to a Python type! The signature was
() -> Set[test_module.Struct]
- The removal of
py::is_operator()
in the binding fixes the problem. - The example does work for version 2.5.0, but fails for 2.6.0, 2.7.1, 2.8.1 and 2.9.0.
- It does also not work for an
std::set
, but for anstd::vector
. - The code was compiled with
clang13.0.0
onx86_64
(Ubuntu20.04)
Reproducible example code
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = ::pybind11;
struct Struct
{
std::string member;
};
bool operator==(const Struct& lhs, const Struct& rhs)
{
return lhs.member == rhs.member;
}
namespace std
{
template <>
struct hash<Struct>
{
std::size_t operator()(const Struct& selector) const;
};
} // namespace std
std::size_t std::hash<Struct>::operator()(const Struct& selector) const
{
return std::hash<std::string>()(selector.member);
}
PYBIND11_MODULE(test_module, module)
{
py::class_<Struct>(module, "Struct")
// Removing the binding makes the example work.
.def(
"__eq__",
[](const Struct& lhs, const Struct& rhs) {
return lhs == rhs;
},
py::is_operator());
module.def("test_func", []() {
return std::unordered_set<Struct>{{"one"}, {"two"}};
});
}