Test issue #2234: binding noexcept methods inherited from an unregistered base class. In C++17 noexcept is part of the function type, so &Derived::noexcept_method resolves to a Base member-function pointer with noexcept specifier. pybind11 must use the Derived type as `self`, not the B
()
| 535 | |
| 536 | |
| 537 | def test_noexcept_base(): |
| 538 | """Test issue #2234: binding noexcept methods inherited from an unregistered base class. |
| 539 | |
| 540 | In C++17 noexcept is part of the function type, so &Derived::noexcept_method resolves |
| 541 | to a Base member-function pointer with noexcept specifier. pybind11 must use the Derived |
| 542 | type as `self`, not the Base type, otherwise the call raises TypeError at runtime. |
| 543 | |
| 544 | Covers all four new cpp_function constructor specialisations: |
| 545 | - Return (Class::*)(Args...) noexcept (set_value) |
| 546 | - Return (Class::*)(Args...) const noexcept (value) |
| 547 | - Return (Class::*)(Args...) & noexcept (increment) |
| 548 | - Return (Class::*)(Args...) const & noexcept (capped_value) |
| 549 | """ |
| 550 | obj = m.NoexceptDerived() |
| 551 | # const noexcept |
| 552 | assert obj.value() == 99 |
| 553 | # noexcept (non-const) |
| 554 | obj.set_value(7) |
| 555 | assert obj.value() == 7 |
| 556 | # & noexcept (non-const lvalue ref-qualified) |
| 557 | obj.increment() |
| 558 | assert obj.value() == 8 |
| 559 | # const & noexcept (const lvalue ref-qualified) |
| 560 | assert obj.capped_value() == 8 |
| 561 | obj.set_value(200) |
| 562 | assert obj.capped_value() == 100 # capped at 100 |
| 563 | |
| 564 | |
| 565 | def test_rvalue_ref_qualified_methods(): |
nothing calls this directly
no test coverage detected