You know that feeling when you open a C++ codebase and it takes 47 seconds just to compile a single translation unit? Yeah. We’ve all been there. And C++26 has a new answer for you: std::indirect.
It’s elegant, actually. A standardized wrapper for the PImpl idiom — that pattern where you hide your class internals behind a pointer so changing the header doesn’t trigger a recompile cascade across half your codebase. std::indirect gives you value semantics, never-null guarantees (except in that wonderfully C++-ish “moved-from state” caveat), and automatic destructor dispatch. It’s clean. It’s modern. It reduces boilerplate.
And it’s treating the symptom, not the disease.
The real problem was never “we need a better way to write PImpl.” The real problem is that C++’s compilation model — headers, includes, the whole preprocessor-driven dependency nightmare — forces PImpl to exist in the first place.
Think about it. PImpl exists because changing a private member variable in your header file shouldn’t force everyone who includes that header to recompile. That’s not a language design choice — that’s a build system deficiency wearing a tuxedo. Every other modern language solved this decades ago. Java has the JVM. Rust has modules. Go has packages. C++ has… a pointer to an incomplete type and a prayer.
Now, don’t get me wrong. std::indirect is genuinely useful if you’re writing or maintaining non-trivial C++ libraries today. It standardizes what every senior C++ developer has been hand-rolling since the 90s. It eliminates the subtle bugs that creep in when you forget to handle move semantics correctly in your manually-written PImpl wrapper. It’s a quality-of-life improvement, no question.
But here’s what keeps me up at night: every C++ release adds features to paper over problems that the language’s foundational architecture created in the first place. std::indirect is the latest in a long line of abstractions designed to make C++ easier — and each one adds another thing developers must learn, must remember, must explain to new team members.
C++ isn’t getting simpler. It’s getting a larger medicine cabinet. And every new pill treats a side effect of the last one.
The comments on the original proposal tell the story. One developer notes that people used to say “you only use a small percentage of C++” — but that’s becoming harder to believe when the percentage keeps growing. Another asks, quite reasonably, whether PImpl is even common enough to warrant standard library support, testing, and documentation. A third wonders about the inevitable gotchas that come with every C++next feature.
These aren’t complaints from people who hate C++. These are the sighs of people who love it enough to still be writing it in 2026.
And there’s a deeper irony here. The moved-from state exception — where std::indirect can technically hold no value — is the same reason we can’t have a non-null unique_ptr. The language’s move semantics, designed to make things safer, created a hole that every abstraction now has to explicitly patch. Every safety feature in C++ comes with an asterisk, and the asterisks are starting to outnumber the features.
The radical solution — the one nobody wants to say out loud — is modules. Real modules. The kind that make header dependencies a relic of the past, that make PImpl unnecessary because changing an implementation detail doesn’t ripple through the build graph like a virus. C++20 introduced modules, yes, but adoption is glacial, tooling support is fragmented, and in the meantime, we get std::indirect.
So here’s where I land. If you’re writing C++ libraries today, use std::indirect. It’s better than hand-rolling PImpl. It’ll save you time, reduce bugs, and make your compile times marginally less soul-crushing. But don’t pretend it’s a solution. It’s a very well-engineered tourniquet.
The question isn’t whether std::indirect is good. It is. The question is how many more layers of abstraction C++ can stack before the whole tower stops making sense to the humans who have to read it.
And that’s a question no standardization committee wants to answer.
FAQ
Q: If std::indirect is just a band-aid, should I even use it?
A: Yes. If you're writing C++ libraries today, std::indirect is strictly better than hand-rolling PImpl. It eliminates move-semantics bugs and reduces boilerplate. Just don't mistake it for a structural solution to C++'s compilation model problem.
Q: What does this mean for my existing C++ codebase?
A: If you're already using PImpl manually, std::indirect can replace it with less code and fewer subtle bugs. If you're not using PImpl, you probably don't need std::indirect — it's specifically for the header-dependency compilation problem.
Q: Is C++ just doomed to keep adding complexity forever?
A: Not forever — but the trajectory suggests yes until modules achieve real adoption and eliminate the need for patterns like PImpl entirely. Until then, every release adds abstractions to patch architectural problems the language was built with.