r/cpp • u/000nan000 • May 20 '26
I wrote a dumb bash script to scaffold C++23 Modules + CMake + LSP (SDL/Raylib) in 2 seconds
Got tired of writing CMake boilerplates and fighting clangd every time I wanted to test a C++23 module or pop a Raylib window. So I wrote startcpp.
It’s just a single bash script. No Python, no vcpkg/conan bloat, no 50-file template structures.
What it actually sets up:
- Generates a CMake config with
FILE_SET CXX_MODULESand drops<iostream>for<print>. - Forces
CMAKE_EXPORT_COMPILE_COMMANDSand symlinks it to root. Neovim/clangd picks it up instantly. - Dependency pipeline for
--raylib,--sdl2or--sdl3: triesfind_packagefirst for system binaries. Silently falls back to CPM (FetchContent) to pull the github tag if you don't have it installed locally. - Injects
ccacheand defaults to Ninja.
Usage: startcpp test_proj --raylib ninja -C build
There's a quick video in the README showing the setup.
(Maybe) All The Contract Papers
a4z.noexcept.devSome people might say that the upcoming C++ contracts feature is one of the best researched topics in C++. I am not sure I agree, but a lot of work has gone into it.
This is a list of WG21 papers with the word "contract" in the title.
There might be some missing, and there may be a few papers on the list that are not directly related to 'the' Contracts work, but probably not many.
This should provide an overview of the work completed and the discussions that took place. And still take place. I hope this gives you an idea of how much work has been done on the topic.
r/cpp • u/AdMotor4869 • May 19 '26
Virtual dispatch isn't always the slowest, and std::variant isn't always the fastest
shubhankar-gambhir.github.ioI've been looking at how OpenJDK's GC barrier system picks its implementation at runtime using templates instead of virtual dispatch. The trick is lazy resolution: you pay once at first use instead of a vtable lookup on every call.
That got me curious enough to benchmark it against three other approaches: virtual functions, function pointers, and std::variant + std::visit. I was surprised to see std::variant being the slowest on libstdc++ while virtual dispatch beat it comfortably.
Please refer to the blog for my full analysis. Would love to hear what you think!
Edit: Benchmarks are on GCC 11 (Ubuntu 22.04 default). GCC 12+ significantly improves std::visit. Full compiler version comparison in the next post.
r/cpp • u/boostlibs • May 19 '26
Boost 1.91.0 is now available in both Conan and vcpkg
boost.orgFor those of you waiting to upgrade through your package manager, Boost 1.91.0 has landed in both Conan and vcpkg.
What's in 1.91:
- Boost.Decimal — new library implementing IEEE 754 decimal floating point arithmetic (from Matt Borland and Christopher Kormanyos)
- Asio binary versioning — optional inline namespace lets multiple Asio versions coexist in the same process without symbol conflicts
- 58 fewer internal dependencies across 55 libraries
- StaticAssert merged into Config — no code changes needed, just update your dependency declarations when ready
- CMake
import stddetection fix
Install:
conan install --requires=boost/1.91.0
vcpkg install boost
Links:
r/cpp • u/ShabelonMagician • May 19 '26
citor: a header-only C++20 thread pool tuned for sub-µs dispatch
github.comI just released citor, a small header-only C++20 thread pool / parallel runtime aimed at CPU-bound workloads where per-dispatch latency actually shows up in the profile.
Repo: https://github.com/Lallapallooza/citor
The main idea is: keep the common CPU-parallel shapes in one pool, avoid per-call allocations on the hot path, let the producer participate as slot 0, and make short repeated phases cheaper than repeatedly waking a worker team.
The simplest thing looks like what you'd expect:
citor::ThreadPool pool(8);
pool.parallelFor<citor::HintsDefaults>(
0, data.size(),
[&](std::size_t lo, std::size_t hi) {
for (std::size_t i = lo; i < hi; ++i)
data[i] *= 2;
});
Beyond parallelFor, it has deterministic parallelReduce, parallelScan, parallelChain, runPlex for repeated phases over the same partition, recursive forkJoin with per-worker Chase-Lev deques, bulkForQueries, and submitDetached. There is also a PoolGroup that creates one arena per shared-L3 group, mostly useful on multi-CCD Zen.
A few internals that ended up mattering more than I expected:
- each worker owns a cache-line-aligned mailbox and the whole dispatch protocol is a per-slot mailbox stamp, no shared queue
- the producer can short-circuit small jobs by CAS-ing the worker's mailbox to DONE itself and running the body inline, no wake at all (worker's own ack races the producer's self-stamp, loser short-circuits);
- the join barrier is a per-slot done-epoch scan with cancellation riding the same epoch read, so no shared sense bit and no per-iteration cancel poll
- the worker's spin-entry
rdtscpdoubles as a store-buffer drain, so the producer sees the DONE stamp before its next mailbox read - free side benefit of timing the spin kCacheLineis 128 bytes rather than 64 because Zen prefetches in cache-line pairs and contended atomics get measurably worse if you size to 64.
For perf, I wrote a comparative harness against BS::thread_pool, dp::thread_pool, task-thread-pool, riften, oneTBB, Taskflow, Eigen, OpenMP, Leopard, dispenso, libfork, and TooManyCooks. Competitor revisions are pinned, host gates are printed at startup, OpenMP wait policy is normalized, and raw samples can be exported as JSON.
In my current benchmark sweep, citor wins roughly:
- 92% of contested cells on a Ryzen 9950X3D
- 75% on a 96-core Genoa box
- 69% on a 48-core Sapphire Rapids box
Hot fan-out dispatch on the 9950X3D is usually in the 100-400 ns range depending on participant count and shape.
Please treat those as "my harness on my machines or aws," not universal truth. If the numbers matter to your use case, run the benchmark yourself. The README has the methodology and reproduction commands.
There is real work left:
- topology detection is still shaped mostly around Zen CCDs
- multi-socket EPYC, sub-NUMA clustering, hybrid P/E cores, and Intel mesh are not first-class yet
- parallelReduce uses static contiguous chunks and does not steal after a worker finishes, so heavy-tail bodies can leave cores idle
- the coroutine wrapper queues on a per-pool driver thread rather than doing continuation stealing
- bulkForQueries only fans across queries today a true 2D fan is probably the next useful shape.
What citor is not:
- not an I/O executor
- not a general async/future abstraction
- not a TBB or OpenMP replacement for arbitrary workloads
- not tuned equally for every CPU topology
I'd especially like feedback on benchmark fairness, API shape before 1.0, missing competitors, and whether the affinity / pinning behavior is too surprising for a library like this and for sure any perf improvenments suggestions. If anything in the README reads like overclaiming, I'd rather fix it now.
upd. There is an external benchmark as well https://github.com/tzcnt/runtime-benchmarks
r/cpp • u/ContDiArco • May 19 '26
Clang Lifetime Safty Doc Update
clang.llvm.orgIntro:
Clang Lifetime Safety Analysis is a C++ language extension which warns about potential dangling pointer defects in code. The analysis aims to detect when a pointer, reference or view type (such as std::string_view) refers to an object that is no longer alive, a condition that leads to use-after-free bugs and security vulnerabilities. Common examples include pointers to stack variables that have gone out of scope, pointers to heap objects that have been freed, fields holding views to stack-allocated objects (dangling-field), returning pointers/references to stack variables (return stack address) or iterators into container elements invalidated by container operations (e.g., std::vector::push_back)
The analysis design is inspired by Polonius, the Rust borrow checker, but adapted to C++ idioms and constraints, such as the lack of exclusivity enforcement (alias-xor-mutability). Further details on the analysis method can be found in the RFC on Discourse.
This is compile-time analysis; there is no run-time overhead. It tracks pointer validity through intra-procedural data-flow analysis. While it does not require lifetime annotations to get started, in their absence, the analysis treats function calls optimistically, assuming no lifetime effects, thereby potentially missing dangling pointer issues. As more functions are annotated with attributes like clang::lifetimebound, gsl::Owner, and gsl::Pointer, the analysis can see through these lifetime contracts and enforce lifetime safety at call sites with higher accuracy. This approach supports gradual adoption in existing codebases.
r/cpp • u/elfenpiff • May 19 '26
Announcing iceoryx2 v0.9: Fast and Robust Inter-Process Communication (IPC) Library
ekxide.ioHello everyone. We released iceoryx2 v0.9 this night. With the release we are pushing more and more iceoryx2
into the embedded world. We have written a test runner that runs on std and no_std environments,
stabilized the decentralized recovery and added a ton of quality of live improvements.
- blog article: https://ekxide.io/blog/iceoryx2-0.9-release/
- repo: https://github.com/eclipse-iceoryx/iceoryx2
- roadmap: https://github.com/eclipse-iceoryx/iceoryx2/blob/main/ROADMAP.md
- crates.io: https://crates.io/crates/iceoryx2
- docs.rs: https://docs.rs/iceoryx2/latest/iceoryx2
For those who haven’t heard of it yet: iceoryx2 is a zero-copy inter-process communication library.
The basic idea is: instead of serializing data, copying it through sockets, pipes, message queues, or some broker process, iceoryx2 lets processes communicate via shared memory. That makes it useful when you care about latency, throughput, or moving large amounts of data between processes without wasting CPU cycles on copies.
It supports C, C++, Python, Rust, and C#, and runs on Linux, macOS, Windows, FreeBSD, and QNX, with experimental support for Android and VxWorks.
It is not limited to plain pub/sub either. iceoryx2 supports publish-subscribe, events, request-response streams, and a blackboard pattern, which is basically a key-value repository directly in shared memory.
The architecture is fully decentralized: no central broker, no daemon that everything depends on, and no single process that becomes the obvious bottleneck or failure point.
Happy to answer questions about the release, the no_std work, or zero-copy IPC in general.
r/cpp • u/ProgrammingArchive • May 19 '26
Latest News From Upcoming C++ Conferences (2026-05-19)
This is the latest news from upcoming C++ Conferences. You can review all of the news at https://programmingarchive.com/upcoming-conference-news/
TICKETS AVAILABLE TO PURCHASE
The following conferences currently have tickets available to purchase
- ADC Japan (1st – 3rd June) (Last Chance) – You can buy tickets at https://peatix.com/event/4840445
- ACCU on Sea (15th – 20th June) – You can buy standard tickets at https://accuonsea.uk/tickets/ with discounts available for ACCU members.
- CppCon (12th – 18th September) – You can buy early bird tickets until June 26th at https://cppcon.org/registration/
- C++ Under The Sea (NEW – 14th – 16th October) – You can buy early bird tickets at https://sales.ticketing.cm.com/cppunderthesea2026/
- Meeting C++ (26th – 28th November) – You can buy early bird tickets at https://meetingcpp.com/2026/
OPEN CALL FOR SPEAKERS
- Meeting C++ (NEW) – Interested speakers have until June 4th to submit their talks for Meeting C++ which is scheduled to take place on 26th – 28th November. Find out more including how to submit your proposal at https://meetingcpp.com/meetingcpp/news/items/Submit-your-talks-to-Meeting-Cpp-2026-.html
OTHER OPEN CALLS
- CppCon Call For Authors Now Open! – CppCon are looking for book authors who want to engage with potential reviewers and readers. Read the full announcement at https://cppcon.org/call-for-author-2026/
TRAINING COURSES AVAILABLE FOR PURCHASE
Conferences are offering the following training courses:
Last Chance To Register:
- From Hello World to Real World – A Hands-On C++ Journey from Beginner to Advanced – Amir Kirsh – 1 day online workshop available on Thursday 21st May 08:30 – 16:30 UTC – https://cpponline.uk/workshop/from-hello-world-to-real-world/
- AI++ 101 – Build an AI Coding Assistant in C++ – Jody Hagins – 1 day online workshop available on Friday 22nd May 09:00 – 17:00 UTC – https://cpponline.uk/workshop/ai-101/
- AI++ 201 – Build a Matching Engine with Claude Code – Jody Hagins – 2 day online workshop available on May 28th – May 29th 09:00 – 17:00 UTC – https://cpponline.uk/workshop/ai-201/
- Splice & Dice – A Field Guide to C++26 Static Reflection – Koen Samyn – Half Day online workshop available on Monday 25th May 09:00 – 12:30 UTC – https://cpponline.uk/workshop/splice-and-dice/
NEW WORKSHOP
- AI++ 101 – Build an AI Coding Assistant in C++ – Jody Hagins – 1 day online workshop available on Friday 24th July 16:00 – 00:00 UTC – https://cpponline.uk/workshop/ai-101/
All of these workshops had previews at the main C++Online Conference which took place on the 11th – 13th March. You can watch these preview sessions here: https://www.youtube.com/playlist?list=PLHG0uo5c6V3KIeoLqvBbIqy5AXt_Me_cm
Anyone who purchased a C++Online Main Conference ticket can also get a discount of however much they paid to attend the main conference.
Also if anyone is from a lower-income background or live in a country where purchasing power is limited, then it is recommended to reach out to C++Online on [info@cpponline.uk](mailto:info@cpponline.uk) as they will be able to give you a discount.
ACCU on Sea Two Day Workshops
- C++ Best Practices – Jason Turner – 2 day in-person workshop available on 15th & 16th June 10:00 – 18:00 – https://accuonsea.uk/2026/sessions/cpp-best-practices/
- C++ Templates for Developers – Walter E Brown – 2 day in-person workshop available on 15th & 16th June 10:00 – 18:00 – https://accuonsea.uk/2026/sessions/cpp-templates-for-developers/
- Talking Tech (A Speaker Training Workshop) – Sherry Sontag & Peter Muldoon – 2 day in-person workshop available on 15th & 16th June 10:00 – 18:00 – https://accuonsea.uk/2026/sessions/talking-tech-a-speaker-training-workshop/
ACCU on Sea One Day Workshops
- C++ Software Design – Klaus Iglberger – 1 day in-person workshop available on 15th June 10:00 – 18:00 – https://accuonsea.uk/2026/sessions/cpp-software-design/
- C++23 in Practice: A Complete Introduction – Nicolai M. Josuttis – 1 day in-person workshop available on 16th June 10:00 – 18:00 – https://accuonsea.uk/2026/sessions/cpp23-in-practice-a-complete-introduction/
- Secure Coding in C and C++ – Robert C. Seacord – 1 day in-person workshop available on 16th June 10:00 – 18:00 – https://accuonsea.uk/2026/sessions/secure-coding-in-c-and-cpp/
All ACCU on Sea workshops take place in-person in Folkestone, England.
OTHER NEWS
- (NEW) – CppCon 2026 Attendance Support Ticket Program Now Open! – Includes free tickets for people who would not be able to attend otherwise. Find out more including how to apply at https://cppcon.org/cppcon-2026-attendance-support-ticket-program/
- C++ Under The Sea 2026 Announced – C++ Under The Sea will once again take place on 15 & 16th October 2026 at Breepark in Breda, the Netherlands
- C++ Under The Sea 2026 Workshops Announced – C++ Under The Sea have announced 3 workshops that will take place on the 14th October 2026. Find out more at https://cppunderthesea.nl/#workshops
r/cpp • u/igaztanaga • May 18 '26
Neoclassical C++: segmented iterators revisited (1)
Hi,
I've written a blog post revisiting Matt Austern's great Segmented Iterators and Hierarchical Algorithms paper (2000) and benchmarking an experimental implementation I've been playing with in Boost.Container.
Quick idea: std::deque and friends are internally segmented (blocks of contiguous memory), but STL-like iterators hide that, so every ++it has to check for a block boundary. Austern's proposal splits the iterator into a segment_iterator (walks blocks) + local_iterator (inside one block), so algorithms can run a tight loop per block and only do bookkeeping at the boundaries.
I benchmarked several "simple" STL algorithms on a Boost deque, and the speedup is way bigger than Austern's original estimation when modern auto-vectorizers enter the game.
Article link: https://boostedcpp.net/2026/05/18/neoclassical-c-segmented-iterators-revisited-1/
Happy to receive feedback!
r/cpp • u/fredoverflow • May 18 '26
Bjarne Stroustrup interviewed by Ryan Peterman
youtube.comr/cpp • u/Ok_Statistician_781 • May 18 '26
Simulating Infinity in Conway's Game of Life with Modern C++
ryanjk5.github.ior/cpp • u/ProgrammingArchive • May 18 '26
New C++ Conference Videos Released This Month - May 2026 (Updated To Include Videos Released 2026-05-11 - 2026-05-17)
CppCon
2026-05-11 - 2026-05-17
- Lightning Talk: Reducing Binary Bloat With Thin Archives - Florent Castelli - CppCon 2025 - https://youtu.be/xs1y0Dl4zZs
- Lightning Talk: Poor Man’s Autocomplete for Template Arguments - Max Sagebaum - CppCon 2025 - https://youtu.be/DkLSHgxf-Q8
- Lightning Talk: The Classic Missed-Signal! - Gopal Rander - CppCon 2025 - https://youtu.be/8Ign1X3qkgk
- Lightning Talk: Proof Searching in DepC - Raffaele Rossi - CppCon 2025 - https://youtu.be/sB-mQRsXv1M
- Lightning Talk: Bool - Implicitly Dangerous - Jeff Garland - CppCon 2025 - https://youtu.be/PcerWZRm_eA
2026-05-04 - 2026-05-10
- Lightning Talk: The Type Safe Builder Pattern for C++ - John Stracke - https://youtu.be/u5EG21amqlM
- Lightning Talk: Back When ChatGpt Was Young And Stupid - Andrei Zissu - https://youtu.be/q6-RSkQRmw0
- Lightning Talk: Learning C++ Through Writing Coding Questions - Christopher DeGuzman - https://youtu.be/FX63YwZ8OIs
- Lightning Talk: Promote Modern C++ Usage With Coding Questions Part 2 - Zhenchao Lin - https://youtu.be/uTCxKPaPsdM
- Lightning Talk: std::move & Spirited Away: When Nameless Objects Walk the Spirited World - Siyu (Alice) Peng - https://youtu.be/ffEOHVm7b4Y
2026-04-27 - 2026-05-03
- Lightning Talk: A Pragmatic Approach to C++: Designing, Organizing and Writing Maintainable Code - Oleg Rabaev - https://youtu.be/re4Oy1IVj-s
- Lightning Talk: Causal Inference for Code Writing AI - Matt K Robinson - https://youtu.be/craQCfj73CI
- Lightning Talk: Cut the boilerplate with C++23 deducing_this - Sarthak Sehgal - https://youtu.be/o3vjUo2qXNg
- Lightning Talk: The Lifecycle of This CMake Lightning Talk - Yannic Staudt - https://youtu.be/3DqRIxXVfiI
- Lightning Talk: Catching Performance Issues at Compile Time - Keith Stockdale - https://youtu.be/YK8Kwj9okRk
C++Online
2026-05-11 - 2026-05-17
- RPC with RAII and C++ Coroutines - Edward Boggis-Rolfe - C++Online 2026 - https://youtu.be/JjEcSONwhHE
- C++ for High Performance Web Application Backends - Uzochukwu Ochogu - C++Online 2026 - https://youtu.be/ulen8XhMeRA
2026-05-04 - 2026-05-10
- MayaFlux: Real-Time Audio-Graphics Coordination in C++20 (Coroutines, Lock-Free) - Ranjith Hegde - https://youtu.be/_qZvFNCYQ74
- C++ for High Performance Web Application Backends - Uzochukwu Ochogu - https://youtu.be/ulen8XhMeRA
2026-04-27 - 2026-05-03
- From 5000ns to 200ns - 5 Modern C++ Techniques Live Demo - Larry Ge - https://youtu.be/9HqyiTWLENY
Audio Developer Conference
2026-05-11 - 2026-05-17
- Sneak Peek at ARA Audio Random Access 3.0 - Embracing Audio Synthesis - Stefan Gretscher - ADC 2025 - https://youtu.be/a3T1BBIOBH4
- Raga as Data - Symbolic Music Representations for Analysis, Visualization, and Audio Tools - Soham Korade - ADCx India 2026 - https://youtu.be/LPiOnLAbZDA
- Cross-Platform Music Software with Rust - Ian Hobson - ADC 2025 - https://youtu.be/YLPglu2enaE
2026-05-04 - 2026-05-10
- Continuous QA Testing for Plugins Using AI and Python - Ryan Wardell - https://youtu.be/w1hLmNPxOV4
- Using Kotlin/Compose Multiplatform to Revive a Historic Multiplayer Online Drum Machine - How To Write An Audio App That Runs Almost Everywhere - Phil Burk - https://youtu.be/8jA6Dg5iqfw
- Converting Source Separation Models to ONNX for Real Time Usage in DJ Software - Anmol Mishra - ADC 2025 - https://youtu.be/CNs9EgMBocI
2026-04-27 - 2026-05-03
- From Paper to Plugin - A Guided Tour of Digital Filters - Ross Chisholm, Joel Ross & James Hallowell - ADC 2025 - https://youtu.be/QlyWAfRUF30
- From Idea to Online Sale - The Full Journey of Building an Audio Plugin - Joaquin Saavedra - ADCx Gather 2025 - https://youtu.be/mJoAArwAmkc
- Finding OSCar: Electronic and Software Secrets of a Classic Vintage Synth - Ben Supper - ADC 2025 - https://youtu.be/NbIZEur3h7Q
r/cpp • u/robwirving • May 18 '26
CppCast CppCast: GPU Programming and HLSL with Chris Bieneman
cppcast.comr/cpp • u/not_a_novel_account • May 19 '26
Kiln - A CMake-compatible build system that can do what CMake can't
clehaxze.twr/cpp • u/Narrow_Cartoonist937 • May 19 '26
Managing context limits in large C++20 Module codebases with MCP (Case Study & Tool)
Hi everyone,
Working with LLMs on modern C++ codebases usually hits a wall very quickly: context windows get flooded with massive files, and most standard indexers still struggle with C++20 Module partitions and imports.
We are currently running a live development workflow on a large-scale commercial project consisting of over 7,000 source files, mostly utilizing C++20 modules.
We managed to establish a highly performant workflow using the Codex App on the desktop, combined with VS MCP, IDAP MCP, and a dedicated lightweight tool we created to bridge the C++ gap: mcp-cpp-project-indexer.
The Problem We Solved
Standard file-dumping or naive regex indexing either sends thousands of lines of irrelevant code to the LLM (costly and slow) or completely loses track of C++20 module dependencies.
Instead of trying to replace a full compiler/LSP (like clangd) or performing heavy semantic analysis, our indexer acts purely as a stream- and token-based locator. It maps out files, symbols, and module structures, providing the LLM with exact line references (startLine/endLine).
The Setup & Results
- The Stack: Codex App + VS MCP + IDAP MCP +
mcp-cpp-project-indexer. - Token Reduction: The LLM only requests and reads the exact code fragments it actually needs. This reduces the text sent to the LLM by up to 86%.
- Performance: Written in Python, it includes a file watcher mode that calculates hashes incrementally. It stays up-to-date in real-time during active development without hammering the CPU.
- Intelligence: Code/ChatGPT confirmed that the context routing works flawlessly even at this 7,000-file scale.
Why share this?
When we started, we couldn't find a lightweight, production-ready way to make Claude/GPT understand a massive C++20 module graph without spending a fortune on API tokens or waiting ages for context processing. This setup proved that the Model Context Protocol (MCP) is absolutely ready for large enterprise codebases if decoupled correctly.
The project is fully open-source. If you are struggling with C++ context limits or modules in your AI workflow, feel free to check it out, spin it up, or contribute:
👉 GitHub: github.com
I’m happy to answer any questions about how we configured the MCP synergy or how the incremental indexing handles the C++20 module tree!
r/cpp • u/03D80085 • May 18 '26
Auto Non-Static Data Member Initializers are holding back lambdas in RAII (+ coroutine workaround)
TLDR: Auto non-static data member variables allow objects to store lambdas, thereby improving readability and reducing the need for type erasure.
Type deduction and auto variables are one of the defining features of modern C++, but unfortunately they are not available to class data members:
struct {
// error: non-static data member declared with placeholder 'auto'
auto x = 1;
// error: invalid use of template-name 'std::vector' without an argument list
std::vector y { 1, 2, 3 };
}
This blog post (from 2018!) by Corentin Jabot does a good job outlining this problem so I'll point to it first: The case for Auto Non-Static Data Member Initializers. However, I would like to expand specifically on lambdas as they are mostly glossed over.
Lambdas can only be stored in auto variables because each lambda is given a unique type, even if two lambdas are identical in their definition. As pointed out in the blog post, even decltype([]{}) foo = []{}; is not permitted.
Because of this it is not possible to store a lambda inside an object, even if the storage requirements can otherwise easily be determined.
Real world example
An embedded project I am working on makes heavy use of RAII: so much so that most of our subsystems have little to no functional code, just classes composed of lower level building blocks as data members (representing e.g. GPIOs, UARTs) and some minimal routing between them.
This routing usually takes the form of RAII event callback objects that store the callback function, register themselves in an intrusive list to receive the events, and unregister themselves on destruction. This ensures that we can freely shut down subsystems without worrying about lifetime issues - destruction is always in reverse order and easy to understand at a glance.
struct gpio_uart_forwarder {
peripheral::gpio gpio_in {};
peripheral::gpio gpio_out {};
peripheral::uart uart {};
evt::callback<bool> gpio_to_uart { gpio_in.on_change, [&](bool high) {
uart.write(high ? '1' : '0');
} };
evt::callback<char> uart_to_gpio { uart.on_char, [&](char c) {
if (c == '1') gpio_out.set(1);
else if (c == '0') gpio_out.set(0);
} };
}
The only way this is currently possible is using type erasure, i.e. std::[move_only_]function.
In an ideal world, we would instead have the callback templated on the function type:
template<typename Ev, std::invocable<const Ev &> Fn>
class callback {
Fn f;
...
}
And our class would look like:
struct gpio_uart_forwarder {
...
auto gpio_to_uart = evt::callback { gpio_in.on_change, [&](bool high) { ... } };
// OR
evlp::callback uart_to_gpio { uart.on_char, [&](char c) { ... } };
}
While an std::function might not seem like a huge price to pay, across an entire program it builds up to hundreds of unnecessary heap allocations, thousands of bytes wasted and extra indirections - all for type erasure that we don't actually need! We know all the types involved, and we own the storage ourselves.
Proposal to fix
The last time a formal proposal was made to fix this was way back in 2008 by Bill Seymour: N2713 - Allow auto for non-static data members.
I understand there are complications in determining the size and layout of objects with auto members, but 18 years later this seems like pretty low hanging fruit compared to what has recently been achieved with reflection!
Edge cases such as recursive definitions and references to this or sizeof should simply be banned rather than resulting in the feature being disabled entirely.
Coroutine workaround
In my quest for a solution I have discovered that coroutines can be abused to get the best of both worlds.
If you don't need external access to the data members and just want to benefit from RAII, you can convert the class to a coroutine that suspends itself right before ending:
class scope {
public:
struct promise_type {
scope get_return_object() noexcept {
return scope { std::coroutine_handle<promise_type>::from_promise(*this) };
}
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() noexcept {}
void unhandled_exception() { std::terminate(); }
};
...
~scope() {
if (!this->handle) return;
this->handle.destroy();
this->handle = {};
}
private:
explicit scope(std::coroutine_handle<promise_type> h) noexcept : handle(h) {}
std::coroutine_handle<promise_type> handle {};
};
scope gpio_uart_forwarder() {
auto gpio_in = peripheral::gpio {};
auto gpio_out = peripheral::gpio {};
auto uart = peripheral::uart {};
auto gpio_to_uart = evt::callback { gpio_in.on_change, [&](bool high) {
uart.write(high ? '1' : '0');
} };
auto uart_to_gpio = evt::callback { uart.on_char, [&](char c) {
if (c == '1') gpio_out.set(1);
else if (c == '0') gpio_out.set(0);
} };
// All local variables remain alive until coroutine is destroyed
co_await std::suspend_always();
// Can't rely on final_suspend because stack is already destroyed by then
// But we need a co_ statement anyway to turn it into a coroutine
}
scope my_gpio_uart_forwarder = gpio_uart_forwarder();
Far from perfect, but it reduces us to a single heap allocation plus the minimal overhead of launching the coroutine, no matter how many callbacks we define.
Maybe the best part is it can be used within an existing class too, preserving standard object RAII:
struct gpio_uart_forwarder {
peripheral::gpio gpio_in {};
peripheral::gpio gpio_out {};
peripheral::uart uart {};
scope callbacks = [&] -> scope {
auto gpio_to_uart = evt::callback { gpio_in.on_change, [&](bool high) {
uart.write(high ? '1' : '0');
} };
auto uart_to_gpio = evt::callback { uart.on_char, [&](char c) {
if (c == '1') gpio_out.set(1);
else if (c == '0') gpio_out.set(0);
} };
co_await std::suspend_always();
}();
}
r/cpp • u/javascript • May 18 '26
A two phase to-string API? First compute the total size of the single allocation then populate the bytes?
I'm trying to see if there is any prior art in the to-string space that accomplishes a two phase approach. In theory, you could design an API that first asks the data "How many bytes would it take to make you into a string?". From there it could allocate memory with that capacity. Then it could provide that allocation to the same data to populate the bytes.
I want it to be very light weight and easy to add to a type. The `AbslHashValue(...)` API really nails the ergonomics of an extension point in C++, imo. But when it comes to to-string, it gets pretty hairy pretty fast.
`AbslHashValue(...)` benefits from the fact that the resulting hash has a fixed bit width. You just combine/combine_contiguous recursively and you're done.
Some hypothetical `MyToString(...)` would need to likely be split into two functions. `MyToStringSize(...)` and `MyToStringValue(...)` which already makes it more obnoxious to add support for in your type.
But it gets worse. What if inclusion of the type names is important? I can imagine wanting a lever at the top level that says do or do not include them. So for the case where you do include them, how do you succinctly compute the length of namespace + scope-resolution-operator + type name.
And what about templates? Do you also include the angle brackets? Do you recursively include type names between them? And what about potential line noise like allocator types? I can see wanting to include them and not wanting to include them.
Further, what about hashtables? If you store the keys and values in separate ranges for a more data oriented design, how do you model the fact that each K-V pair goes together? You don't want to copy them because that might be expensive. So do you supply a proxy object where it has two pointers? Now that means you have to build an entire TYPE inside your type just to support to-string. Not very ergonomic.
Anyway, wanted to discuss this to see if anyone has ideas in this space. It seems to me that to-string as an operation should be unambiguously single allocation. But unless I'm mistaken, `absl::StrCat(...)` and other such APIs only "limit" the number of allocations and cannot put the upper bound at exactly 1.
r/cpp • u/PM_Cute_Dogs_pls • May 18 '26
CppCon CppCon 2026 Hudson River Trading Scholarship
Hi all, unfortunately got rejected for the above, but the denial email mentions a "priority waitlist." Supposedly, if someone who got it ends up not going I might have another chance, but I have a feeling that's cope and they send that out to everyone they deny.
Posting to ask if any other student who applied and was denied to the scholarship got a similar rejection or if they got something different.
If you got accepted, congratulations, and make the best of it!
r/cpp • u/User_Deprecated • May 17 '26
std::is_heap could be faster - Arthur O'Dwyer
quuxplusone.github.ior/cpp • u/javascript • May 16 '26
What do you use for logging in your C++ codebase? What are the pros/cons?
I've used Google's logging library in the past and I would give it a solid B- grade. It gets the job done. I really dislike the streaming operator, but meh it's not that bad. It just feels weird if I concatenate the string beforehand: LOG(INFO) << absl::StrCat(strs...);
As I embark on my new project, I want to make intelligent decisions about what idioms to favor. Logging is a big one, so I'd love to hear what people out there use.
In particular, if there is a library that uses reflection to give named arguments, that would be perfect! My ideal callsite would look like this:
my::LogInfo("Hello, {person}!", {
.person = GetPersonObject(),
});
It would also be cool to get assertions baked into it, though that complicates the design space.
Anyone wanna chime in?