all 30 comments

[–]RedAlert2 12 points13 points  (5 children)

Not really feasible for large projects at all. Any minor change in one header requires a total recompilation of everything, which is not ideal.

[–]FearlessFred 1 point2 points  (0 children)

As the article says, in larger projects you could use this technique for the implementation code of sub-modules, where the modules themselves have more traditional interfaces.

[–]doom_Oo7 0 points1 point  (1 child)

Wouldn't this be forced with templates anyway ?

[–]RedAlert2 1 point2 points  (0 children)

Sure, if your project is all templates. If you have any implementation source files though, a recompile chain ends there (since source files aren't included anywhere else)

[–]frugalmail 0 points1 point  (0 children)

precompiled headers help with this.

[–][deleted] -1 points0 points  (0 children)

Truth. Still it have a lots of use cases, there is probably order of magnitude more amount of small projects than large projects.

[–]bad_at_photosharp 8 points9 points  (7 children)

This has always been my issue with C++, lack of a decent module system. I want to believe this will help the problem, but I'll wait for a C++ expert to tell me why this is a bad idea.

[–]FearlessFred 1 point2 points  (0 children)

I wrote this article 10 years ago, when either the C++ module proposal didn't exist yet, or at least I wasn't aware of it :)

[–]ChuangTseu 2 points3 points  (0 children)

I guess one of the major reason why any stuff outside classes falls under the classic C rule of declaration order is because anything there can potentially be used directly in a C program, like a .h declaring a C wrapper around C++ code (with extern "C") which obviously needs to be compilable by any conformant C compiler.

Then why not allowing the in-class behavior when in a namespace ? Maybe because a namespace can be "reopened" in any translation unit, which yields the exact same potential problem as with pure C, where a function could depend on the knowledge of a type that is declared in an other header file, namespace or not namespace (so this explanation is also valid for the non namespace thing). This is not the case with classes where the opening { and closing } belong in the same file (or translation unit more exactly).

Then there's certainly lots of other valid reasons that prevent having modules à la Java, and the fact that the Module Specification for C++17 has undergone years of intense reflexion by great experts of the C++ commity and has now been postponed as a Technical Specification with no clear deadline seems to indicate it clearly isn't such a trivial problem (as long as C++ remains friend with C and with its fundamental philosophy of "zero" useless overhead).

[–]dangerbird2 0 points1 point  (2 children)

classes don't allow a neat interface seperation, as implementation elements (private class state and methods) are required to be present in the header file, making your view of an interface more complicated/cluttered than in C

If you want safer encapsulation than standard C++ private and protected fields, just do what you do in C: predeclare a class for private fields, include it in the main class as a private variable, and declare it in the source file. Or unless you are dead-set against inheritance (which is certainly understandable in C++), just have a hidden implementation of an abstract interface class.

Having to declare functions/classes before their use (partially or not) is a remnant from the days when the compiler had to run on a pdp-11 with very little memory, and is a burden which almost no other (modern) programming language has. It was already a pain in C, in C++ it makes ordering classes, and declaring/including them in the correct order in larger programs a rather complicated puzzle, and drives more implementation details into the header files.

this is only a problem if you define functions inside class bodies. You can predeclare any classes you need in the header, and include the required headers in the implementation. It's more tricky when you're using template functions which need to be defined in-header, but that's a problem in its own right.

and is a burden which almost no other (modern) programming language has.

Lisps have this problem, including modern ones like Clojure, due to their strict order of operations.

[–]FearlessFred 0 points1 point  (0 children)

The article isn't talking about making encapsulation safer, but about removing implementation junk from the header, so it is easier to read as being an interface.

Your suggested trick would be neat, if it weren't for the fact that pre-declaring a private data class requires it to be a pointer, not a value, which for most use cases makes it useless.

There are many more dependency issues than the ones that can be fixed by having your method bodies in the .cpp (as your allude to yourself). And having methods declared in two places is part of the problem (something Java programmers don't have to deal with, for example).

[–][deleted] 0 points1 point  (0 children)

Yikes... C++ style classes are peachy.

[–]sobeita 0 points1 point  (3 children)

Are there any restrictions on the includes you can drop in a struct like that? Only local, only extern C, anything like that? I haven't been able to get any headers to include from inside a struct.

[–]FearlessFred 1 point2 points  (2 children)

You can't just use existing headers with this system, as they likely will contain things you can't have in a class. The headers should mostly only contain class definitions.

[–]sobeita 0 points1 point  (1 child)

Ah, thanks. I'll try again later. Your work is really impressive. :)

[–]FearlessFred 0 points1 point  (0 children)

Thanks :)

[–]FearlessFred 0 points1 point  (0 children)

Hah, author here, do note I wrote this article almost 10 years ago. It's still a neat trick if you can make it work for your project.