РЕДАКТИРОВАТЬ : Я только что обнаружил, что pybind11 имеет вспомогательную конструкцию, которая делает то же самое, что приводит к гораздо более простому и понятному коду. Замените блок PYBIND11_MODULE
в исходном ответе следующим текстом:
PYBIND11_MODULE(mseal, m) {
py::class_<Ciphertext>(m, "Ciphertext")
.def(py::init<>())
.def("scale",
py::overload_cast<>(&Ciphertext::scale, py::const_),
"returns a constant reference to the scale")
.def("scale_nonconst",
py::overload_cast<>(&Ciphertext::scale),
"returns a reference to the scale");
}
Исходный ответ: вам потребуется decltype
, чтобы получить тип возврата, и std::declval
, чтобы устранить неоднозначность перегрузки для decltype
. Ниже приведен полный рабочий пример (минимум C ++ 14), где я добавил неконстантную версию, чтобы показать, что у вас есть полный контроль над выбором:
#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include <iostream>
#include <utility>
namespace py = pybind11;
class Ciphertext {
public:
inline auto &scale() noexcept {
std::cerr << "non-const called" << std::endl;
return scale_;
}
inline auto &scale() const noexcept {
std::cerr << "const called" << std::endl;
return scale_;
}
private:
int scale_;
};
PYBIND11_MODULE(mseal, m) {
py::class_<Ciphertext>(m, "Ciphertext")
.def(py::init<>())
.def("scale",
static_cast<decltype(std::declval<Ciphertext const&>().scale()) (Ciphertext::*)() const>(&Ciphertext::scale),
"returns a constant reference to the scale")
.def("scale_nonconst",
static_cast<decltype(std::declval<Ciphertext&>().scale()) (Ciphertext::*)()>(&Ciphertext::scale),
"returns a reference to the scale");
}
Который при компиляциив mseal.so
работает как положено:
>>> import mseal
>>> mseal.Ciphertext().scale()
const called
0
>>> mseal.Ciphertext().scale_nonconst()
non-const called
0
>>>