Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't split up my code manually for the compiler, I do it for the humans, being compiler friendly is just a pleasant side effect. You can build java files the same way without header files, worst case scenario is you have some fat compilation units.


> I don't split up my code manually for the compiler, I do it for the humans, being compiler friendly is just a pleasant side effect.

There is no human benefit to having to copy and paste function signatures—and worse, the bodies of functions you want to be inlined, including all templates—into header files. There's also no benefit to having the compiler parse hundreds of KB of header files over and over and over again.

> You can build java files the same way without header files, worst case scenario is you have some fat compilation units.

Java (production implementations used in practice) performs whole program optimization via its JIT. It's nice for Java, but that isn't how Rust works.


I don't disagree on the header files, no sane language designed today would include that.

> Java (production implementations used in practice) performs whole program optimization via its JIT. It's nice for Java, but that isn't how Rust works.

Whole program optimization isn't generally something you want on dev builds, which is where incremental compilation is useful. For a production build why wouldn't you do a full rebuild anyway?


> Whole program optimization isn't generally something you want on dev builds, which is where incremental compilation is useful.

By "whole program optimization" I also include things like generic/template instantiation. Whenever you use, say, a HashMap, you have to recompile the implementation of the HashMap specialized to the size, alignment, destructor, etc. of types you're using with it.

> For a production build why wouldn't you do a full rebuild anyway?

When I profile apps written in Rust, it's important for me to be able to get good turnaround time on optimized builds.


Do Java generics work like that? I thought the JVM did not know about the generics as the types are erased at compile time.


JVM doesn't know about generic types at the runtime. There's no specialization of HashMaps, it's just arrays of points to objects all around.

With project Valhalla: https://en.wikipedia.org/wiki/Project_Valhalla_(Java_languag... there's been talk about specialization for value types.


It is already available for those that want to play with it.

https://adoptopenjdk.gitbooks.io/adoptopenjdk-getting-starte...


I too thought the same. That's why pcwalton's comment confused me.


Rust generics do. Java's don't.


Splitting up code into headers and sources also helps keep interfaces separate from implementations. It allows one to not only read just the header for the full interface, but it also allows one to distribute the implementation in binary form and the interface in source form, which is important for companies.


Except for inlineable functions and templates in C++—which become a greater and greater fraction of code the more "modern" your C++ gets. Not to mention that the size of your instance variables leaks into your public interface unless you manually heap allocate and use the pimpl idiom.

In any case, Rust stores the interfaces to libraries in serialized binary form (including documentation, following a standardized format understood by rustdoc), and they can be readily extracted from crates using tools that ship with the language. So what you describe isn't a benefit of headers anyhow.


"C++ did it right" seems a separate position from that put forward by the parent comment.

I definitely think there's benefit to being able to view interface as separate from implementation, although that might well be better supported by tooling (editor folding, documentation generation) than manual maintenance - which you seem to be doing well.

I don't know whether there is benefit to being able to edit interface separately from implementation. Probably not much of one, but I could certainly be convinced otherwise.


Usually if you edit the interface, you also have to edit the implementation. The only time I've ever wanted to edit an interface alone is when there wasn't any implementation written yet, which makes it a moot point anyway.


If you make substantive changes, for sure.

It's possible that you may want to make cosmetic changes (or maybe change how you're specializing something where the implementation is more polymorphic?).

Still, I certainly don't see much of an argument that being able to edit the two separately has much value. I'm just not entirely convinced of non-existence.


One usually does want the reverse though, editing the implementation without touching the interface.


Writing applications which have an API other people write plugins against is one: commercial apps ship the .h files, against which plugin-writers only have those and build plugins for the host apps.

Yes you still obviously have to keep them in sync, but the point is you (as a commercial software vendor) can ship just the headers and keep the internal implementation details secret and change how things work completely. Which is useful for commercial vendors of software.


This is a common myth about .h files versus modules.

Most languages with native support for modules do have the necessary information stored in the binary file to enable this scenario.

The only problem is exposing those plugins across languages, but it isn't a big problem if the OS has a rich ABI instead of a C one. For example COM on Windows, or WinRT the improved version of it.


This isn't really an argument for .h files though.

.h files are an extra amount of work you have to put in. In the case of plugin APIs, this is work you'd have to put in anyway (for a fraction of the .h files -- the ones which are part of the API). But that work doesn't have to be put in elsewhere.

This is an argument for interface description files for plugins, but that could always have been done by a language with idl files or something. Indeed, apps in most other languages define interfaces via .h files because that's the de-facto plugin API description format, but they don't use .h files everywhere in the source. They only use them where necessary for the API.


You can do this in Rust just fine. The compiler can determine all the types and signatures from the tables stored in binary code. No separate .h file needed.


Two seconds of google found a .h file generator: http://www.radwin.org/michael/2011/05/10/stubgen/ . I'm sure there are others.


> Except for inlineable functions and templates in C++—which become a greater and greater fraction of code the more "modern" your C++ gets.

The C++ ABI is currently not portable anyway. So the concern about templates (or any C++ features) forcing you to put the implementation into the header file would not apply in the scenario dllthomas was referring to:

If you want to distribute your library as a binary object and a separate source-form interface/header today, you'll have to use a (wrapper) C API. Regardless of how "modern" the C++ code is.

Of course, it would be nice to have portable C++ objects some time in the future which would change things... :)


> If you want to distribute your library as a binary object and a separate source-form interface/header today, you'll have to use a (wrapper) C API.

This is only true if you want to target different compilers. If you ship your binaries targeting a specific compiler (which is what just about every company does that I've ever worked with), you don't have any abi issues.


Actually, you can even have incompatibilities with the same compiler and different compile flags. So to reliably build a "semi-portable" c++ object one would have to ensure that all objects are compiled with the exact same (i.e. same version of the compiler/same compiler source code) and with the exact same flags. I'm sure there are some compiler vendors that offer ABI backwards-compatibility but it's not part of the C++ language per-se.

See this article by Herb Sutter on the topic: https://isocpp.org/files/papers/n4028.pdf


Oh I'm well aware; as my comment indicated, I've been doing this a long time. I didn't want to get in to the full details in a HN comment, but yes, there's definitely a few things you have to coordinate on between vendors if you want to ship C++ libraries that work together.


> If you want to distribute your library as a binary object and a separate source-form interface/header today, you'll have to use a (wrapper) C API. Regardless of how "modern" the C++ code is.

Not really.

Those of us on Windows make use of COM, or since Windows 8, UWP components (formally known as WinRT).


Yes, but this is only a solution if your library is only targeting windows.

If you want users of any standards-compliant C++ implementation to be able to use your library today, you'll still have to go with c-abi symbols or ship the sources. All other worakrounds are vendor-specific and not part of the standard.

[Of course even objects containing only C symbols are not portable across platforms either, but at least the C ABI/calling convention is more or less strictly defined for any given target platform. Assuming no other platform-specific stuff like glibc is used]




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: