c++ 通过pybind11实现正确的相等运算符

8zzbczxx  于 2023-03-05  发布在  其他
关注(0)|答案(2)|浏览(183)

我正在使用pybind11公开一个C++类,我想公开一个__eq__方法,这是我目前正在做的事情:

pybind11_class.def("__eq__", [](const MyClass &self, const myClass &other) {
    return self.value == other.value;
});

问题是,当与其他类型的对象进行比较时,这会导致类型错误,而在这种情况下正确的行为是不存在错误,并将等式计算为false。
如何正确地实现相等操作符?理想情况下,我希望只定义一个方法重载,以避免污染pybind11公开的docstring。

6yjfywim

6yjfywim1#

不要试图直接定义__eq__方法,而是通过定义pybind11::self == pybind11::self来告诉pybind你想要一个equality方法,它将处理“对于其他类型返回false”语义:

auto pybind11_class = pybind11::class_<...>(...);

pybind11_class.def(pybind11::self == pybind11::self);
pybind11_class.def(pybind11::self != pybind11::self);

要使其正常工作,C++类必须具有operator==operator!=运算符,并且必须具有#include <pybind11/operators.h>

332nm8kg

332nm8kg2#

这对我很有效。在类的绑定代码中,包含类的等式运算符,如图所示。

#include <pybind11/operators.h>
namespace py = pybind11;

PYBIND11_MODULE(name, m)
{
    py::class_<Data>(m, "Data")
        .def(py::self == py::self)
        .def(py::self != py::self);
}

然后在类代码中添加一个友元作为相等运算符重写

class Data
{
public:

    bool friend operator==(const Data& lhs, const Data& rhs)
    {
        if (strcmp(lhs.data->tag, rhs.data->tag)) {
            return false;
        }
        else {
            return true;
        }
    }

    bool friend operator!=(const Data& lhs, const Data& rhs)
    {
        if (strcmp(lhs.data->tag, rhs.data->tag)) {
            return true;
        }
        else {
            return false;
        }
    }
}

这与上面的答案基本相同,虽然答案是正确的,但并不包括编译过程中遇到的问题,即pybind11绑定代码引用的等式操作符覆盖必须作为友元实现才能编译。标准C++等式覆盖是一个单独的实体,占用主覆盖名称空间。
注意,这里显示的示例代码不是工作代码,实现主体的其余部分被省略了。

相关问题