diff --git a/robotpy_build/autowrap/render_cls_rpy_include.py b/robotpy_build/autowrap/render_cls_rpy_include.py index 5e245136..57e15716 100644 --- a/robotpy_build/autowrap/render_cls_rpy_include.py +++ b/robotpy_build/autowrap/render_cls_rpy_include.py @@ -194,7 +194,7 @@ def _render_cls_trampoline( r.write_trim( f""" template - struct PyTrampoline_{ cls.full_cpp_name_identifier } : PyTrampolineBase, virtual py::trampoline_self_life_support {{ + struct PyTrampoline_{ cls.full_cpp_name_identifier } : PyTrampolineBase {{ using PyTrampolineBase::PyTrampolineBase; """ ) diff --git a/robotpy_build/autowrap/render_pybind11.py b/robotpy_build/autowrap/render_pybind11.py index e6962b87..66bfb49c 100644 --- a/robotpy_build/autowrap/render_pybind11.py +++ b/robotpy_build/autowrap/render_pybind11.py @@ -292,7 +292,16 @@ def cls_consts(r: RenderBuffer, cls: ClassContext): def cls_decl(r: RenderBuffer, cls: ClassContext): if cls.trampoline: tctx = cls.trampoline - r.writeln(f"using {tctx.var} = {tctx.full_cpp_name};") + # py::trampoline_self_life_support + r.write_trim( + f""" + struct {tctx.var} : {tctx.full_cpp_name}, py::trampoline_self_life_support {{ + using RpyBase = {tctx.full_cpp_name}; + using RpyBase::RpyBase; + }}; + + """ + ) r.writeln( f'static_assert(std::is_abstract<{tctx.var}>::value == false, "{cls.full_cpp_name} " RPYBUILD_BAD_TRAMPOLINE);' ) diff --git a/tests/cpp/rpytest/ft/__init__.py b/tests/cpp/rpytest/ft/__init__.py index 3057fc0e..9e919f01 100644 --- a/tests/cpp/rpytest/ft/__init__.py +++ b/tests/cpp/rpytest/ft/__init__.py @@ -7,6 +7,7 @@ ClassWithFields, ClassWithIgnored, ClassWithTrampoline, + ConstexprTrampoline, DocAppendClass, DocAppendEnum, DocClass, @@ -123,6 +124,7 @@ "ClassWithFields", "ClassWithIgnored", "ClassWithTrampoline", + "ConstexprTrampoline", "DocAppendClass", "DocAppendEnum", "DocClass", diff --git a/tests/cpp/rpytest/ft/include/trampoline.h b/tests/cpp/rpytest/ft/include/trampoline.h index 0f152147..663f1a03 100644 --- a/tests/cpp/rpytest/ft/include/trampoline.h +++ b/tests/cpp/rpytest/ft/include/trampoline.h @@ -38,3 +38,19 @@ struct ClassWithTrampoline { // bug: ensure this doesn't get forwarded ClassWithTrampoline(const int &name) {} }; + + +struct ConstexprTrampoline { + constexpr ConstexprTrampoline() = default; + constexpr virtual ~ConstexprTrampoline() = default; + constexpr virtual int fn() const = 0; +}; + +struct ChildConstexprTrampoline : ConstexprTrampoline { + constexpr ChildConstexprTrampoline(int i) : something(i) {} + constexpr int fn() const override { + return 1; + } + + int something; +}; diff --git a/tests/test_ft_trampoline.py b/tests/test_ft_trampoline.py index e64f9275..35fe0f49 100644 --- a/tests/test_ft_trampoline.py +++ b/tests/test_ft_trampoline.py @@ -1,4 +1,4 @@ -from rpytest.ft import ClassWithTrampoline +from rpytest.ft import ClassWithTrampoline, ConstexprTrampoline def test_class_with_trampoline(): @@ -25,3 +25,7 @@ def fnWithMoveOnlyParam(self, i): c = PyClassWithTrampoline() assert ClassWithTrampoline.check_moveonly(c) == 8 + + +def test_constexpr_trampoline(): + ConstexprTrampoline()