Enums¶
A welded enum — scoped or unscoped — binds via the same weld_type<T> entry point
(dispatched to the enum path by is_enum_v). Each enumerator resolves like a
data member: the enum's policy plus per-enumerator exclude/include marks
decide what binds. What it becomes in the target language differs:
- Python — a stdlib
enum.IntEnum(pybind11py::native_enum, nanobindnb::is_arithmetic; int-convertible). - Lua — a plain
name → valuetable (Lua has no enum type).
In the cookbook
Recipe 01 — One of everything welds a scoped enum and
asserts the IntEnum surface from Python.
Grammar: the annotation goes after the enumerator name
Unlike a struct member (whose annotation precedes it), a C++ enumerator's annotation comes after its name:
Scoped enum, automatic policy¶
enum class
[[=welder::weld(welder::lang::py, welder::lang::lua)]]
Direction {
North,
East,
South [[=welder::mark::exclude]], // excluded → not bound
West // keeps its C++ value (3)
};
Excluding an enumerator does not renumber the rest — West is still 3. The
enumerator stays qualified under the enum name:
Unscoped enum — values exported¶
An unscoped enum also mirrors its enumerators onto the enclosing module unqualified
(pybind11 export_values(); the sol2 rod copies the names onto the module
table), matching C++:
Scoped enum, opt-in policy¶
enum class
[[=welder::weld(welder::lang::py, welder::lang::lua), =welder::policy::opt_in]]
Level {
Debug [[=welder::mark::include]],
Info [[=welder::mark::include]],
Trace // not opted in → not bound
};
Enum-typed members¶
An enum-typed member or parameter binds because the enum is welded — bind the enum first (like a welded base), then the type that uses it:
When you bind a whole namespace, declaration order handles this for you — put the enums before the structs that use them.
Per-enumerator docs ride in the enum's class docstring
A doc on an individual enumerator has no per-member docstring slot the
Python stub tools surface (a stub lists a member as a bare Name = value), so
welder folds it into the enum's class docstring as an Attributes section —
the one place pybind11-stubgen / nanobind's stubgen carries it into the
.pyi:
class Direction(enum.IntEnum):
"""
A compass bearing.
Attributes:
North: towards the pole
East: sunrise
"""
The section is spelled in the rod's docstring
style — Google Attributes:, NumPy
underlined Attributes, Sphinx :var:. An
undocumented enumerator contributes no line; an excluded one appears nowhere.
The Lua rods have no runtime docstring, so they ignore it at load time; the
LuaCATS stub instead emits each enumerator's
doc as a --- comment above its entry in the ---@enum table (the language
server attaches that to the member, shown on hover/completion). The doc also
reaches the C++ reference, where the Doxygen filter surfaces it
as a trailing /**< */ comment. How docs flow in general is covered later, in
Docstrings.
Next: Inheritance.