Live data from Hacker News

What to do with C++ modules?

nibblestew.blogspot.com

261–269 of 269 posts

Re: What to do with C++ modules?

#261
post #248

Earlier quoted context omitted.

> So what you’re saying is that it takes time, but works out? Probably depends on what you mean by "works out". I don't think GP would agree that delivering a less capable alternative qualifies. For example, one major feature C++0x concepts was supposed to have but got removed was definition-time checking - i.e., checking that your template only used capabilities promised by the concepts it uses, so if you defined a…

C++0x was ~5 years ago. C++26 concepts has more or less everything you mention, and you can try it out with all the major compilers right now.

> C++0x was ~5 years ago.

You're quite a bit off. Tialaramex covered this well enough.

> C++26 concepts has more or less everything you mention, and you can try it out with all the major compilers right now.

Uh, no. No, it doesn't. Here's an example I wrote up earlier that demonstrates how concepts (still) don't have definition-time checking:

    #include 

    template
    concept fooable = requires(T t) {
        { t.foo() } -> std::same_as;
    };

    struct only_foo {
        int foo();
    };

    struct foo_and_bar {
        int foo();
        int bar();
    };

    template
    int do_foo_bar(T t) {
        t.bar(); // No definition-time error despite fooable not specifying the presence of bar()
        return t.foo();
    }

    // Succeeds despite fooable only requiring foo()
    template int do_foo_bar(foo_and_bar t);

    // Fails even though only_foo satisfies fooable
    // template int do_foo_bar(only_foo t);
Here's Clang 21.1.0 compiling this in C++26 mode: https://cpp.godbolt.org/z/znPGvcTqs . Note that as-is the snippet compiles fine, but if you uncomment the last line you get an error despite only_foo satisfying fooable.

Contrast this with Rust:

trait Fooable { fn foo(self) -> i32; }

fn do_foo_bar(t: T) -> i32 { let _ = t.bar(); // error[E0599]: no method named `bar` found for type parameter `T` in the current scope t.foo() }

Notice how do_foo_bar didn't need to be instantiated for the compiler to catch the error. That's what C++ concepts are unable to do, and as far as I know there is nothing on the horizon to change that.

Re: What to do with C++ modules?

#262
post #247

Earlier quoted context omitted.

> See the other versions I added. I don't think those work either. Not only do neither of those actually end the lifetime of what's passed in, but they have other flaws as well. > template void drop(T &&) {} This literally does nothing. Reference parameters don't affect what's passed in on their own - you need at least something on the other end (e.g., a move constructor) to do anything. For example, consider how thi…

> Not only do neither of those actually end the lifetime of what's passed in >For example, consider how this would be instantiated for std::vector : Great, here you go. https://godbolt.org/z/9v66n6Ta4 And yes, the compiler will not prevent you from using this value. (clang will eventually, I think) But clang static analyzer will happily detect it. https://stackoverflow.com/questions/72532377/g-detect-use-af...

> Great, here you go.

As I pointed out, your drop_new is broken for copyable types. For example, consider std::array:

    auto w = std::array{0, 1, 2};
    drop_new(std::move(w));
    std::cerr 
This prints "0, 1, 2". Rust's drop() doesn't suffer from this flaw.

> And yes, the compiler will not prevent you from using this value.

Yes, that is the point!

This bit:

    std::vector vec {1, 2, 3};
    drop_new(std::move(vec));
    std::cerr 
Simply does not compile in Rust [0]:

    let vec = vec![1, 2, 3];
    drop(vec);
    println!("{0} 
[0]: https://rust.godbolt.org/z/GjcMYnEzq

> But clang static analyzer will happily detect it.

One problem is that you're not guaranteed to catch it, similarly to why static analyzers aren't guaranteed to catch use-after-frees.

Re: What to do with C++ modules?

#263
post #251

Earlier quoted context omitted.

I'm not entirely sure modules systems must face that limitation. C++'s module system, for example, permits separation of module interfaces and module implementations, much like the existing header/implementation system. IIRC OCaml's module system does something similar, though I'm not familiar enough with it to say whether it qualifies as a module system beyond the name. Speaking more abstractly even if there isn't a…

> Speaking more abstractly even if there isn't an explicit interface/implementation separation perhaps compilers could pick out and make available interface information "ahead of time" to alleviate/possibly eliminate the effect of otherwise problematic dependency chains? I'm not sure how well this would work for non-instantiated templates > There's also the question of whether super large projects must have problemat…

> I'm not sure how well this would work for non-instantiated templates

I don't know either, but I was thinking about module systems in general rather than C++'s module system specifically, since the original comment I was responding to seemed to be speaking in generalities as well for that particular topic.

> Any header precompilation dependency chain is a dependency chain and may end up worse than fully parallel TU compilation if the time to parse said headers is faster than the time to compile them in a serial way.

Right, but it comes down to whether it's literally impossible to structure super large projects in a practical manner. Sure, maybe you eat some slowdown, maybe you get some speedup, but I'm a bit skeptical that modules must result in slowdowns of such a magnitude that super large projects are infeasible.

Re: What to do with C++ modules?

#264

Back in the 90s, I implemented precompiled headers for my C++ compiler (Symantec C++). They were very much like modules. There were two modes of operation: 1. all the .h files were compiled, and emitted as a binary that could be rolled in all at once 2. each .h file created its own precompiled header. Sounds like modules, right? Anyhow, I learned a lot, mostly that without semantic improvements to C++, while it made…

> just finish the job and relegate the preprocessor to the dustbin. Yup, I think this is the core of the problem with C++. The standards committee has drawn a bad line that makes encoding the modules basically impossible. Other languages with good module systems and fast incremental builds don't allow for preprocessor style craziness without some pretty strict boundaries. Even languages that have gotten it somewhat w…

I actually think this attitude is the reason modules are so slowly adopted. The committee did exactly what you suggest and relegated the preprocessor to the dustbin and modules are seeing slow adoption.

The truth is 98% of the preprocessor is fine - it's ifdefs for platforms and defines of constants and inline functions that are defined exactly once and never redefined. Because modules supports none of this, that means we can't modulize Windows.h. Or zlib. Or gtest.

The committee should have remembered that one of the selling points of C++ is C compatibility, and figured out a way to get modules to work with 98% or the preprocessor and forbid only the nasty 2%.

Re: What to do with C++ modules?

#265

Earlier quoted context omitted.

Thing is (correct.me if Im wrong), that if you use modules, all of your code need to use modules (e.g. you cant have mixed #include and import ; in your project). Which rules out a lot of 3rd party code you might want to depend on.

you wrong You can simply use modules with includes. If you will #include vector inside your purview then you will just get a copy of the vector in each translation unit. Not good, but works. On the other hand. If you include a vector inside the global module fragment, then the number of definitions will be actually 1, even if you include it twice in different modules.

Well, the standard says you can, but it doesn't actually work in practice in msvc, which is the only compiler that's supported modules for over a year.

Re: What to do with C++ modules?

#266

Earlier quoted context omitted.

D modules are very fast. Many of our customers rely on D being way faster than C++ to compile.

I often hear about a lot of advantages of D. So I don't understand why it is so unpopular. Probably I need to give it a chance, but I'm unsure that I will find a real job with the D stack.

D is fine. Like many languages that postdate C++ and Java, it made better choices, learning from the past. But it doesn't really have a differentiator.

Re: What to do with C++ modules?

#267

Earlier quoted context omitted.

> just finish the job and relegate the preprocessor to the dustbin. Yup, I think this is the core of the problem with C++. The standards committee has drawn a bad line that makes encoding the modules basically impossible. Other languages with good module systems and fast incremental builds don't allow for preprocessor style craziness without some pretty strict boundaries. Even languages that have gotten it somewhat w…

I actually think this attitude is the reason modules are so slowly adopted. The committee did exactly what you suggest and relegated the preprocessor to the dustbin and modules are seeing slow adoption. The truth is 98% of the preprocessor is fine - it's ifdefs for platforms and defines of constants and inline functions that are defined exactly once and never redefined. Because modules supports none of this, that mea…

> The committee did exactly what you suggest and relegated the preprocessor to the dustbin

Importantly, no they did not.

They put a boundary on the preprocessor containing preprocessing within the module definition and not the code importing the module.

And that's where a lot of the loss and compatibility problems have come into play. That's why you can't, for example, share a module between builds. Because the ifdefs that built the module in the first place may have changed from one build to the next.

It was good that the committee bound the preprocessor, but they simply didn't go far enough.

C++ is making strides to adding the language features needed to dustbin modules. A lot of the work of consteval can replace a lot of what the preprocessor is doing.

> Because modules supports none of this, that means we can't modulize Windows.h. Or zlib. Or gtest.

And see, that's the issue. Modules do actually support all this. We can in fact modularize windows.h, zlib, or gtest. The issue is the `windows.module` still has to be rebuilt with every application that imports it because those `ifdefs` could evaluate differently depending on what env variables the build system sets before building. The module can't be just a simple AST built once. Maybe once for a project, but that's about it. And that's the rub. Change anything that causes the module to recompile and you spend exactly the same time you'd spend on precompiled headers.

Re: What to do with C++ modules?

#268

Earlier quoted context omitted.

you wrong You can simply use modules with includes. If you will #include vector inside your purview then you will just get a copy of the vector in each translation unit. Not good, but works. On the other hand. If you include a vector inside the global module fragment, then the number of definitions will be actually 1, even if you include it twice in different modules.

Well, the standard says you can, but it doesn't actually work in practice in msvc, which is the only compiler that's supported modules for over a year.

gcc and clang implemented them too, but partialy.

My comment about this absolutely wrong point:

> all of your code need to use modules

With all three major compilers you can right now use modules and at the same time include some other dependencies.

Re: What to do with C++ modules?

#269

Earlier quoted context omitted.

how are modules related to dependencies in general? You can use your modules at the same time using dependencies via includes. And this works well.

Can't include _any_ header downstream if you import std, it is also unknown how you're gonna export and share modules across dependencies you have no indention of 'porting' to modules...

why everyone is fixated around `import std`?? Its only one library. If you can't use `import std` this is not mean that you can't use modules...

> it is also unknown how you're gonna export and share modules across dependencies you have no indention of 'porting' to modules...

as a first step you can introduce modules only in private interfaces of your lib. This is also absolutely valid usage..

There is no solution to invent modules in such way that everyone just switch compiler flag and have fun. If you expect this, so...

Post reply on HN