welder 0.1.0
Bindings for annotated C++ types, from C++26 reflection
Loading...
Searching...
No Matches
trampoline.hpp File Reference

Virtual-function overriding support shared by welder's Python backends. More...

#include <cstddef>
#include <meta>
#include <string_view>
#include <vector>
#include <welder/diag.hpp>
#include <welder/vocabulary.hpp>
Include dependency graph for trampoline.hpp:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  welder::rods::python::bind_flat_spec
 The stored form of a bind_flat mark (a plain tag — it carries no state). More...
struct  welder::rods::python::trampoline_spec
 The stored form of a trampoline mark (a plain tag — it carries no state). More...
struct  welder::rods::python::scanned_trampoline
 The outcome of scanning a base's namespace for its trampoline-annotated subclass. More...

Namespaces

namespace  welder
namespace  welder::rods
namespace  welder::rods::python
namespace  welder::rods::python::detail

Functions

consteval bool welder::rods::python::bound_flat (std::meta::info entity)
 Does entity (a type or a member function) carry a bind_flat mark?
consteval bool welder::rods::python::is_trampoline (std::meta::info type)
 Does type carry a trampoline mark?
consteval scanned_trampoline welder::rods::python::scanned_trampoline_of (std::meta::info base)
 Find the trampoline-annotated class deriving directly from base by scanning base's enclosing namespace.
consteval bool welder::rods::python::is_overridable_virtual (std::meta::info member)
 Is member an overridable virtual — a virtual member function that welder routes through the trampoline?
consteval bool welder::rods::python::detail::same_slot (std::meta::info a, std::meta::info b)
 Do a and b declare the same vtable slot?
consteval void welder::rods::python::detail::collect_virtuals (std::meta::info type, std::vector< std::meta::info > &slots)
 Accumulate the most-derived declaration of every virtual member function reachable in type's complete object into slots, deduplicating by vtable slot (same_slot — name + parameters + cv/ref, so a covariant override is one slot, not two).
consteval std::vector< std::meta::info > welder::rods::python::overridable_virtuals (std::meta::info type)
 Every overridable virtual slot of type — the ones welder routes through a trampoline — folding in virtuals inherited from any base.
consteval std::meta::info welder::rods::python::virtual_slot (std::meta::info type, std::string_view name, std::meta::info fn_type)
 The overridable virtual slot of type named name whose function type is fn_type — the hand-written disambiguator for an overloaded virtual.
consteval std::size_t welder::rods::python::virtual_slot_count (std::meta::info type)
 The number of overridable virtual member functions of type, inherited ones included.
consteval bool welder::rods::python::has_virtual_methods (std::meta::info type)
 Does type declare or inherit any overridable virtual method?
template<class T>
consteval std::meta::info welder::rods::python::construction_type_of ()
 The type welder constructs when binding T: its registered/annotated trampoline if one exists, else T itself.
consteval bool welder::rods::python::declares_override (std::meta::info tramp, std::meta::info vfn)
 Does trampoline declare an override for the virtual method vfn?
consteval bool welder::rods::python::trampoline_covers (std::meta::info type, std::meta::info tramp)
 Does tramp override every virtual method of type — inherited ones included?

Variables

constexpr bind_flat_spec welder::rods::python::bind_flat {}
 Mark a virtual entity as deliberately bound non-overridably.
template<class T>
constexpr std::meta::info welder::rods::python::trampoline_for = std::meta::info{}
 The trampoline subclass registered for T, or a null reflection if none.
constexpr trampoline_spec welder::rods::python::trampoline {}
 Mark a class as the trampoline for the base it derives from — the annotation form of trampoline_for.

Detailed Description

Virtual-function overriding support shared by welder's Python backends.

pybind11 and nanobind both let a Python subclass override a C++ virtual method, but only if the class is bound with a trampoline — a C++ subclass that captures each virtual call and forwards it to Python (nanobind's NB_TRAMPOLINE / PYBIND11_OVERRIDE). welder cannot synthesize that subclass: generating the override declarations needs member-declaration injection, which C++26 reflection (P2996) does not provide (its only class-synthesis facility, std::meta::define_aggregate, adds data members only). The vtable also forces each override to be a real member function sharing the base method's exact name.

So the trampoline is still hand-authored — but reflection automates everything around* it, and this header holds the backend-neutral half:

  • virtual_slot_count / has_virtual_methods — how many overridable slots a type has (the NB_TRAMPOLINE(Base, N) count, never hand-maintained);
  • trampoline_for — the user's T → trampoline registration hook (a specializable variable template, the type-level analogue of welder::trust_bindable), read by each Python rod's class-creation primitive to bind class_<T, Trampoline> instead of class_<T>;
  • bind_flat — the opt-out marker for a virtual type that is deliberately bound non-overridably (C++-produced, never subclassed in Python);
  • trampoline_covers — the compile-time coverage check (every virtual of T is overridden in the trampoline), so a forgotten override is a build error, not a method that silently never reaches Python.

The per-override dispatch body and the authoring macros are backend-specific and live in each rod's own trampoline.hpp (welder/rods/python/nanobind/…, …/pybind11/…); those spell the neutral WELDER_PY_TRAMPOLINE / WELDER_PY_OVERRIDE differently so one trampoline source compiles under either Python rod.

Requires the welder vocabulary first (#include <welder/vocabulary.hpp>), like the rest of the reflection layer.

Definition in file trampoline.hpp.