[HN Gopher] C++ Modules Are Here to Stay
       ___________________________________________________________________
        
       C++ Modules Are Here to Stay
        
       Author : faresahmed
       Score  : 68 points
       Date   : 2026-01-24 06:49 UTC (5 days ago)
        
 (HTM) web link (faresbakhit.github.io)
 (TXT) w3m dump (faresbakhit.github.io)
        
       | whobre wrote:
       | > auto main() -> int {
       | 
       | Dude...
        
         | on_the_train wrote:
         | It's been the go-to syntax for 15 years now
        
           | Night_Thastus wrote:
           | Go-to? I've never seen a project use it, I've only ever seen
           | examples online.
        
             | whobre wrote:
             | Same here
        
           | cpburns2009 wrote:
           | Now I haven't touched C++ in probably 15 years but the
           | definition of main() looks confused:
           | 
           | > auto main() -> int
           | 
           | Isn't that declaring the return type twice, once as auto and
           | the other as int?
        
             | yunnpp wrote:
             | No. The auto there is doing some lifting so that you can
             | declare the type afterwards. The return type is only
             | defined once.
             | 
             | There is, however, a return type auto-deduction in recent
             | standards iirc, which is especially useful for lambdas.
             | 
             | https://en.cppreference.com/w/cpp/language/auto.html
             | 
             | auto f() -> int; // OK: f returns int
             | 
             | auto g() { return 0.0; } // OK since C++14: g returns
             | double
             | 
             | auto h(); // OK since C++14: h's return type will be
             | deduced when it is defined
        
               | maccard wrote:
               | What about
               | 
               | auto g() -> auto { return 0.0; }
        
               | yunnpp wrote:
               | 0.0 is a double, so I would assume the return type of g
               | is deduced to be double, if that is what you're asking.
        
             | maccard wrote:
             | I really wish they had used func instead, it would have
             | saved this confusion and allowed for "auto type deduction"
             | to be a smaller more self contained feature
        
               | zabzonk wrote:
               | the standard c++ committee is extremely resistant to
               | introducing new keywords such as "func", so as not to
               | break reams of existing code.
        
         | CamperBob2 wrote:
         | It's like calling a Ford Mustang Mach-E the "Model T++."
        
         | few wrote:
         | And their code example doesn't actually return a value!
        
           | Davidbrcz wrote:
           | For main it's explicitly allowed by the standard, and no
           | return is equal to return 0
        
         | webdevver wrote:
         | i was sincerely hoping i could get                   auto
         | main(argc, argv) -> int              int argc;
         | char **argv;
         | 
         | to work, but alas it seems c++ threw pre-ansi argument type
         | declarations out.
        
           | zabzonk wrote:
           | > c++ threw pre-ansi argument type declarations out
           | 
           | they never were in C++.
        
         | sethops1 wrote:
         | As someone who quit c++ over 15 years ago it's been comical to
         | watch what this language has become.
        
         | rovingeye wrote:
         | This has been valid C++ since C++ 11
        
         | cocoto wrote:
         | In my opinion this syntax is super good, it allows to have all
         | functions/method names starting at the same level, it's way
         | easier to read the code that way, huge readability improvement
         | imo. Sadly nobody uses this and you still have the classic way
         | so multiple ways to do the same thing...
        
           | vitaut wrote:
           | This style is used in {fmt} and is great for documentation,
           | especially on smaller screens:
           | https://fmt.dev/12.0/api/#format_to_n
        
       | cmovq wrote:
       | Can someone using modules chime in on whether they've seen build
       | times improve?
        
         | nickelpro wrote:
         | import std; is an order of magnitude faster than using the STL
         | individually, if that's evidence enough for you. It's faster
         | than #include <iostream> alone.
         | 
         | Chuanqi says "The data I have obtained from practice ranges
         | from 25% to 45%, excluding the build time of third-party
         | libraries, including the standard library."[1]
         | 
         | [1]:
         | https://chuanqixu9.github.io/c++/2025/08/14/C++20-Modules.en...
        
           | luke5441 wrote:
           | Yeah, but now compare this to pre-compiled headers. Maybe we
           | should be happy with getting a standard way to have pre-
           | compiled std headers, but now my build has a "scanning" phase
           | which takes up some time.
        
         | vitaut wrote:
         | We did see build time improvements from deploying modules at
         | Meta.
        
       | feelamee wrote:
       | why use modules if PCH on your diagram is not much worse in
       | compile times?
        
         | nickelpro wrote:
         | Macro hygiene, static initialization ordering, control over
         | symbol export (no more detail namespaces), slightly higher
         | ceiling for compile-time and optimization performance.
         | 
         | If these aren't compelling, there's no real reason.
        
         | bluGill wrote:
         | modules are the future and the rules for are well thought out.
         | Ever compiler has their own version of PCH and they all work
         | different in annoying ways.
        
           | Maxatar wrote:
           | Modules are the future... and will always be the future.
        
         | WalterBright wrote:
         | Having implemented PCH for C and C++, it is an uuugly hack,
         | which is why D has modules instead.
        
       | reactjs_ wrote:
       | Here's the thing I don't get about module partitions: They only
       | seem to allow one level of encapsulation.
       | Program         - Module           - Module Partition
       | 
       | whereas in module systems that support module visibility, like
       | Rust's, you can decompose your program at multiple abstraction
       | levels:                   Program         - Private Module
       | - Private Module             - Private Module             -
       | Public Module           - Public Module
       | 
       | Maybe I am missing something. It seems like you will have to rely
       | on discipline and documentation to enforce clean code layering in
       | C++.
        
         | pdpi wrote:
         | Rust's re-exports also allow you to design your public module
         | structure separate from your internal structure.
        
         | groby_b wrote:
         | I don't think you're missing something. The standards committee
         | made a bad call with "no submodules", ran into insurmountable
         | problems, and doubled down on the bad call via partitions.
         | 
         | "Just one more level bro, I swear. One more".
         | 
         | I fully expect to sooner or later see a retcon on why really,
         | two is the right number.
         | 
         | Yeah, I'm salty about this. "Submodules encourage dependency
         | messes" is just trying to fix substandard engineering across
         | many teams via enforcement of somewhat arbitrary rules. That
         | has never worked in the history of programming. "The determined
         | Real Programmer can write FORTRAN programs in any language" is
         | still true.
        
           | bluGill wrote:
           | The C++ committee tries to do features with room for future
           | extension. They believe that whatever you want from sub-
           | modules is still possible in the future - but better to have
           | a small (as if modules is small) thing now than try for
           | perfects. We can argue about submodules once we have the easy
           | cases working and hopefully better understand the actual
           | limitations.
        
             | groby_b wrote:
             | Not to put too fine a point on it: The world has 35 years
             | of experience with submodules. It's not rocket science. The
             | committee just did what committees do.
             | 
             | And sure, "future extension" is nice. But not if the future
             | arrives at an absolutely glacial pace and is technically
             | more like the past.
             | 
             | This may be inevitable given the wide spread of the
             | language, but it's also what's dooming the language to be
             | the next COBOL. (On the upside, that means C++ folks can
             | write themselves a yacht in retirement ;)
        
           | pklausler wrote:
           | FWIW, Fortran _does_ have submodules.
        
         | pjmlp wrote:
         | Like most languages with modules.
         | 
         | Rust, Modula-2 and Ada are probably the only ones with module
         | nesting.
        
           | IsTom wrote:
           | Notably many languages in ML family have first class modules.
        
             | pjmlp wrote:
             | Only Standard ML and OCaml, as far as I am aware.
             | 
             | However this is a different kind of modules, with them
             | being present on the type system, and manipulated via
             | functors.
        
       | w4rh4wk5 wrote:
       | https://arewemodulesyet.org/ gives you an overview which
       | libraries already provide a module version.
        
         | srcreigh wrote:
         | Wow, the way this data is presented is hilarious.
         | 
         | Log scale: Less than 3% done, but it looks like over 50%.
         | 
         | Estimated completion date: 10 March 2195
         | 
         | It would be less funny if they used an exponential model for
         | the completion date to match the log scale.
        
           | w4rh4wk5 wrote:
           | Yeah, my personal opinion is that modules are dead on
           | arrival, but I won't waste my time arguing with C++
           | enthusiasts on that.
        
             | mcdeltat wrote:
             | Nah I'm a C++ (ex?) enthusiast and modules are cool but
             | there's only so many decades you can wait for a feature
             | other languages have from day 1, and then another decade
             | for compilers to actually implement it in a usable manner.
        
       | TimorousBestie wrote:
       | I can't deploy C++ modules to any of the hardware I use in the
       | shop. Probably won't change in the near-to-mid future.
       | 
       | It seems likely I'll have to move away from C++, or perhaps more
       | accurately it's moving away from me.
        
         | bluGill wrote:
         | If you tools are not updated that isn't the fault of C++. You
         | will feel the same about Rust when forced to used a 15 year old
         | version too (as I write this Rust 1.0 is only 10 years old).
         | Don't whine to me about these problems, whine to your vendors
         | until they give you the new stuff.
        
           | Joker_vD wrote:
           | > whine to your vendors until they give you the new stuff.
           | 
           | How well does this usually work, by the way?
        
           | krior wrote:
           | Nobody is "whining" to you. Nobody is mentioning rust. Your
           | tone is way too sharp for this discussion.
        
           | TimorousBestie wrote:
           | If C++ libraries eschew backward compatibility to chase after
           | build time improvements, that's their design decision. I'll
           | see an even greater build time improvement than they do
           | (because I won't be able to build their code at all).
        
           | juliangmp wrote:
           | My experience with vendor toolchains is that they generally
           | suck anyway. In a recent bare metal project I chose not to
           | use the vendor's IDE and toolchain (which is just an old
           | version of GCC with some questionable cmake scripts around
           | it) and instead just cross compile with rust manually. And so
           | far its been a really good decision.
        
             | TimorousBestie wrote:
             | Yep, this aligns with my experience. I've yet to take the
             | plunge into cross compiling with rust though, might have to
             | try that.
        
           | jcranmer wrote:
           | > If you tools are not updated that isn't the fault of C++.
           | 
           | It kinda is. The C++ committee has been getting into a bad
           | habit of dumping lots of not-entirely-working features into
           | the standard and ignoring implementer feedback along the way.
           | See https://wg21.link/p3962r0 for the incipient implementer
           | revolt going on.
        
             | 20k wrote:
             | Its happening again with contracts. Implementers are
             | raising implementability objections that are being
             | completely ignored. Senders and receivers are being claimed
             | to work great on a GPU but without significant testing
             | (there's only one super basic cuda implementation), and
             | even a basic examination shows that they won't work well
             | 
             | So many features are starting to land which feel
             | increasingly DoA, we seriously need a language fork
        
             | amluto wrote:
             | Even some much simpler things are extremely half baked. For
             | example, here's one I encountered recently:
             | alignas(16) char buf[128];
             | 
             | What type is buf? What alignment does that type have? What
             | alignment does buf have? Does the standard even say that
             | alignof(buf) is a valid expression? The answers barely make
             | sense.
             | 
             | Given that this is the recommended replacement for
             | aligned_storage, it's kind of embarrassing that it works so
             | poorly. My solution is to wrap it in a struct so that at
             | least one aligned type is involved and so that
             | static_assert can query it.
        
           | crote wrote:
           | When one of the main arguments people use to stick to C++ is
           | that it "runs everywhere", it _actually is_. After all, what
           | use is there for a C++ where the vast majority of the library
           | ecosystem only works with the handful of major compilers? If
           | compatibility with a broad legacy ecosystem isn 't important,
           | there are far more attractive languages these days!
           | 
           | Just like Python was to blame for the horrible 2-to-3 switch,
           | C++ is to blame for the poor handling of modules. They
           | shouldn't have pushed through a significant backwards-
           | incompatible change if the wide variety of vendor toolchains
           | wasn't willing to adopt it.
        
         | maccard wrote:
         | This is not an argument against modules. This is an argument
         | against allowing areas that don't upgrade hold modern c++ back.
        
       | rienbdj wrote:
       | From the outside looking in, this all feels like too little too
       | late. Big tech has decided on Rust for future infrastructure
       | projects. C++ will get QoL improvements... one day and the
       | committees seem unable to keep everyone happy or disappoint one
       | stake holder. C++ will be around forever, but will it be
       | primarily legacy?
        
         | 20k wrote:
         | Yes. Unfortunately the committee has completely abandoned
         | safety at this point. Even memory/thread safety profiles have
         | been indefinitely postponed. The latest ghost safety lifetimes
         | thing is completely unimplementable
         | 
         | There literally isn't a plan or direction in place to add any
         | way to compete with Rust in the safety space currently. They've
         | got maybe until c++29 to standardise lifetimes, and then C++
         | will transition to a legacy language
        
       | Night_Thastus wrote:
       | The fact that precompiled headers are nearly as good for a much
       | smaller investment tells you most of what you need to know, imo.
        
       | fooker wrote:
       | C++ templates and metaprogramming is fundamentally incompatible
       | with the idea of your code being treated in modules.
       | 
       | The current solution chosen by compilers is to basically have a
       | copy of your code for every dependency that wants to specialize
       | something.
       | 
       | For template heavy code, this is a combinatorial explosion.
        
         | pjmlp wrote:
         | It has worked perfectly fine while using VC++, minus the usual
         | ICE that still come up.
        
           | fooker wrote:
           | It works perfectly when it comes to `import std` and making
           | things a bit easier.
           | 
           | It does not work very well at all if your goal is to port
           | your current large codebase to incrementally use modules to
           | save on compile time and intermediate code size.
        
             | pjmlp wrote:
             | Office has made a couple of talks about their modules
             | migration, which is exactly that use case.
        
         | WalterBright wrote:
         | D has best-in-class templates and metaprogramming, and modules.
         | It works fine.
        
         | amluto wrote:
         | I think that SFINAE and, to a lesser extent, concepts is
         | fundamentally a bit odd when multiple translation units are
         | involved, but otherwise I don't see the problem.
         | 
         | It's regrettable that the question of whether a type meets the
         | requirements to call some overload or to branch in a particular
         | if constexpr expression, etc, can depend on what else is in
         | scope.
        
       | yunnpp wrote:
       | I recently started a pet project using modules in MSVC, the
       | compiler that at present has best support for modules, and ran
       | into a compiler bug where it didn't know how to compile and asked
       | me to "change the code around this line".
       | 
       | So no, modules aren't even here, let alone to stay.
       | 
       | Never mind using modules in an actual project when I could repro
       | a bug so easily. The people preaching modules must not be using
       | them seriously, or otherwise I simply do not understand what weed
       | they are smoking. I would very much appreciate to stand
       | corrected, however.
        
         | senfiaj wrote:
         | I still hope that modules become mature and safe for production
         | code. Initially I coded in C/C++ and this header
         | #include/#ifndef approach seemed OK at that time. But after
         | using other programming languages, this approach started to
         | feel too archaic. No sane programming language should require a
         | duplication in order to export something (for example, the full
         | function and its prototype), you should write something once
         | and easily export.
        
           | kccqzy wrote:
           | > No sane programming language should require a duplication
           | in order to export something (for example, the full function
           | and its prototype)
           | 
           | You are spoiled by the explosive growth of open source and
           | the ease of accessing source code. Lots of closed source
           | commercial libraries provide some .h files and a .so file.
           | And even when open source, when you install a library from a
           | package from a distribution or just a tarball, it usually
           | installs some .h files and a .so file.
           | 
           | The separation between interface and implementation into
           | separate files was a good idea. The idea seemed to be going
           | out of vogue but it's still a good idea.
        
             | senfiaj wrote:
             | > Lots of closed source commercial libraries provide some
             | .h files and a .so file.
             | 
             | I'm mostly talking about modules for internal
             | implementation, which is likely to be the bulk of the
             | exports. Yes, it's understandable that for dll / so files
             | exporting something for external executables is more
             | complicated also because of ABI compatibility concerns (we
             | use things like extern "C"). So, yes header approach might
             | be justified in this case, but as I stated, such exports
             | are probably a fraction of all exports (if they are needed
             | at all). I'll still prefer modules when it's possible to
             | avoid them.
        
             | AgentME wrote:
             | In most situations, auto-generating the equivalent of .h
             | files for a library based on export statements in the
             | source code would be fine and a useful simplification.
        
             | johannes1234321 wrote:
             | > The separation between interface and implementation into
             | separate files was a good idea. The idea seemed to be going
             | out of vogue but it's still a good idea.
             | 
             | However as soon as you do C++ that goes away. With C++ you
             | need implementation of templates available to the consumer
             | (except cases with limited set of types where you can
             | extern them), wmin many cases you get many small functions
             | (basic operator implementations, begin()/end() for
             | iterators in all variations etc.) which benefit from
             | inking, thus need to be in the header.
             | 
             | Oh and did I mention class declarations tonthe the class
             | size ... or more generic and even with plain C: As soon as
             | the client should know about the size of a type (for being
             | able to allocate it, have an array of those etc) you can't
             | provide the size by itself, but you have to provide the
             | full type declaration with all types down the rabbit hole.
             | Till you somewhere introduce a pointer to opaque type
             | indirection.
             | 
             | And then there macros ...
             | 
             | Modules attempt to do that better, by providing just the
             | interface in a file. But hey, C++ standard doesn't "know"
             | about those, so module interface files aren't a portable
             | thing ...
        
           | Maxatar wrote:
           | I think everyone hopes/hoped for a sane and useful version of
           | modules, one that would provide substantial improvements to
           | compilation speed and make things like packaging libraries
           | and dealing with dependencies a lot more sane.
           | 
           | The version of modules that got standardized is anything but
           | that. It's an incredibly convoluted mess that requires an
           | enormous amount of effort for little benefit.
        
             | senfiaj wrote:
             | > It's an incredibly convoluted mess that requires an
             | enormous amount of effort for little benefit.
             | 
             | I'd say C++ as a whole is a complete mess. While it's
             | powerful (including OOP), it's complicated and inconsistent
             | language with a lot of historical baggage (40+ years).
             | That's why people and companies still search for (or even
             | already use) viable replacements for C++, such as Rust,
             | Zig, etc.
        
         | malfmalf wrote:
         | They are using modules in the MS Office team:
         | 
         | https://devblogs.microsoft.com/cppblog/integrating-c-header-...
        
           | Maxatar wrote:
           | This is untrue. The MS Office team is using a non-standard
           | MSVC compiler flag that turns standard #include into header
           | units, which treats those header files in a way similar to
           | precompiled header files. This requires no changes to source
           | code, except for some corner cases they mention in that very
           | blog post to work around some compiler quirks.
           | 
           | That is not the same as using modules, which they have not
           | done.
        
         | bluGill wrote:
         | Modules are still in the early adoptor phase - despite 3 years.
         | there are unfortunately bugs, and we still need people to write
         | the "best practices for C++ modules" books. Everyone who has
         | use them overall says they are good things and worth learning,
         | but there is a lot about using them well that we haven't
         | figured out.
        
           | alextingle wrote:
           | Best practice for C++ modules: avoid.
           | 
           | (Buy my book)
        
         | vitaut wrote:
         | Modules have been working reasonably well in clang for a while
         | now but MSVC support is indeed buggy.
        
       | up2isomorphism wrote:
       | "C includes show it age." But C++ is stating not because of there
       | is a "++" there but because of there is a "C".
        
       | fasterik wrote:
       | I get by without modules or header files in my C++ projects by
       | using the following guidelines:
       | 
       | - Single translation unit (main.cpp)
       | 
       | - Include all other cpp files in main
       | 
       | - Include files in dependency order (no forward declarations)
       | 
       | - No circular dependencies between files
       | 
       | - Each file has its own namespace (e.g. namespace draw in
       | draw.cpp)
       | 
       | This works well for small to medium sized projects (on the order
       | of 10k lines). I suspect it will scale to 100k-1M line projects
       | as long as there is minimal use of features that kill compile
       | times (e.g. templates).
        
       | jokoon wrote:
       | I am curious to know if that 8.6x speedup is consistent.
       | 
       | I don't see many "fair" benchmarks about this, but I guess it is
       | probably difficult to properly benchmarks module compilation as
       | it can depend on cases.
       | 
       | If modules can reach that sort of speedup consistently, it's
       | obviously great news.
        
       ___________________________________________________________________
       (page generated 2026-01-29 23:01 UTC)