| 3518 | |
| 3519 | template <typename InputType, typename OutputType> |
| 3520 | void implicitly_convertible() { |
| 3521 | struct set_flag { |
| 3522 | bool &flag; |
| 3523 | explicit set_flag(bool &flag_) : flag(flag_) { flag_ = true; } |
| 3524 | ~set_flag() { flag = false; } |
| 3525 | |
| 3526 | // Prevent copying/moving to ensure RAII guard is used safely |
| 3527 | set_flag(const set_flag &) = delete; |
| 3528 | set_flag(set_flag &&) = delete; |
| 3529 | set_flag &operator=(const set_flag &) = delete; |
| 3530 | set_flag &operator=(set_flag &&) = delete; |
| 3531 | }; |
| 3532 | auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * { |
| 3533 | thread_local bool currently_used = false; |
| 3534 | if (currently_used) { // implicit conversions are non-reentrant |
| 3535 | return nullptr; |
| 3536 | } |
| 3537 | set_flag flag_helper(currently_used); |
| 3538 | if (!detail::make_caster<InputType>().load(obj, false)) { |
| 3539 | return nullptr; |
| 3540 | } |
| 3541 | tuple args(1); |
| 3542 | args[0] = obj; |
| 3543 | PyObject *result = PyObject_Call(reinterpret_cast<PyObject *>(type), args.ptr(), nullptr); |
| 3544 | if (result == nullptr) { |
| 3545 | PyErr_Clear(); |
| 3546 | } |
| 3547 | return result; |
| 3548 | }; |
| 3549 | |
| 3550 | if (auto *tinfo = detail::get_type_info(typeid(OutputType))) { |
| 3551 | tinfo->implicit_conversions.emplace_back(std::move(implicit_caster)); |
| 3552 | } else { |
| 3553 | pybind11_fail("implicitly_convertible: Unable to find type " + type_id<OutputType>()); |
| 3554 | } |
| 3555 | } |
| 3556 | |
| 3557 | inline void register_exception_translator(ExceptionTranslator &&translator) { |
| 3558 | detail::with_exception_translators( |
nothing calls this directly
no test coverage detected