TGViewer
C++ - Reddit C++ - Reddit @r_cpp · 227 subscribers
Post #23960 15
A Month of Writing Reflections-based Code: What have I learned?

## Preface

I have been trying to automate writing my own pybind11 binding code with the help of C++26 reflections, as implemented by [clang-p2996](https://github.com/bloomberg/clang-p2996).

There were moments where things went smoothly, but also moments where I missed a feature or two from the world of reflections. Then there is also accidental complexity caused by pybind11 having features which are, at the very least, not friendly for generic binding generation.

Before I begin, a massive thanks to Barry Revzin, Daveed Vandevoorde, Dan Katz, Adam Lach and whoever else worked on bringing Reflections to C++.

## Smooth sailing

What we got from the set of reflections papers is awesome. Here's an example of what can be achieved quite easily:

https://godbolt.org/z/jaxT8Ebjf

With some 20 lines of reflections, we can generate bindings that cover:

- free functions (though not overload sets of free functions - more on that later)
- structs/classes with
- a default constructor
- member functions
- data members, though always writable from python

You can also see how this easily generalizes to all other kinds of `py_class.def_meow(...)`. Almost...
Since C++ does not have "properties" in the python sense, `def_property_meow` will need [special care](https://godbolt.org/z/MT5ojzG4n).

As the `def_property` example shows, customizing the generated bindings is possible with `[[=annotations]]`.

So far... this is AWESOME. Looks like we can make bindings for whatever C++ entity we fine.

 

Well, let's talk about the not so awesome parts of this adventure. In order from least troublesome to most troublesome

## Splicing ranges

Pybind11 likes to work with template parameter packs, but C++26 often leaves us with `std::vector<std::meta::info>`.
We can deal with this in multiple ways:

 

Options are:

- good old [`index_sequece`](https://godbolt.org/z/5vEM7dWhr)
- [structured bindings can introduce a pack](https://godbolt.org/z/GooGTsWdc)
- But constexpr structured bindings have not been implemented yet in clang-p2996

And one thing that didn't end up in [P2996](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2996r13.html#range-splicers) are [range splicers](https://godbolt.org/z/TPWqv3jss).

 

So this can be done. Depending on the context, it can even look elegant, but I often missed costexpr structured bindings and ended up reaching for `index_sequence` a lot.

 

Range splicers would have been nice, but I can live without them.

## Code duplication due to pybind11 design

Pybind11 has a lot of similar functions with different names:

`def` vs `def_static` vs `def_property` vs `def_property_readonly` vs ...

Then there are also things whose mere presence alters what pybind11 is doing, without a no-op state:

`is_final` for classes, `arithmetic` for enums and so on.

These can be handled with an `if constexpr` that branches on existence of annotation, however, this leads to a lot of code duplication.
Here, token sequences as described in https://wg21.link/P3294 would remove most of repetition. For the `def_meow` stuff, an approximate reduction in amount of code is ~10x.

## Pure virtual bases

To use these with pybind11, users need to write ["trampolines"](https://godbolt.org/z/ffPKE7Gxb), because it needs to be able to instantiate a python object representing the base class object.

C++26 still can't generate types that have member function, but this will be solved with https://wg21.link/P3294

## Templates can't be annotated

It would be useful to annotate member function templates with something like

template_inputs({
{.name = "T1Func", .args = {^^T1}},
{.name = "T2T3Func", args = {^^T2, ^^T3}}
})

And then bind the same template multiple times, under different names and with different template arguments. However [that's not possible right now](https://godbolt.org/z/qx5c1v417). Can templates even have attributes and annotations?

## Function parameter missing features

**Parameter annotations can
GitHub GitHub - bloomberg/clang-p2996: Experimental clang support for WG21 P2996 (Reflection). Experimental clang support for WG21 P2996 (Reflection). - bloomberg/clang-p2996
More from @r_cpp
  1. Oct 17, 2026"C++23 - The Complete Guide" now as Paperback C++23 - The Complete Guide is now also avail…
  2. Oct 17, 2026A quick C++ standard container overview https://meetingcpp.com/blog/items/A-quick-Cpp-stan…
  3. Oct 17, 2026The Double Headed Stack Allocator – The blog at the bottom of the sea https://blog.demofox…
  4. Oct 17, 2026Barry's C++ Blog - Generating Operator Functions https://brevzin.github.io/c++/2026/10/14/…
  5. Oct 17, 2026MSVC Build Tools Version 14.52 Release Candidate Now Available https://devblogs.microsoft.…
  6. Oct 17, 2026C++ futures part 4: What if I want an immediate on-thread std::async? https://devblogs.mic…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →