CppCoreGuidelines icon indicating copy to clipboard operation
CppCoreGuidelines copied to clipboard

Consider amending SF.1 and not recommending .h extensions by default

Open eyalroz opened this issue 3 years ago • 16 comments

Rule SF.1 recommends using .h as the C++ header file name suffix, with the rationale being:

Headers are more often shared with C to compile as both C++ and C, which typically uses .h, and it’s easier to name all headers .h instead of having different extensions for just those headers that are intended to be shared with C

But this rationale is relevant only in code which intended to involve both C and C++, at least in principle. These kinds of codebases are, IMHO, the minority; and certainly they are not an overwhelming majority. In fact, as the language evolves, one writes more and more code which is farther away from C, and whose headers are never intended to never be shared with C code. In those case (which, again, are either the majority or a large minority of cases), it is better to remove the ambiguity of potential C compatibility by using a C-incompatible header file suffix (e.g. .hpp or .hh) - as there are no "just those headers... to be shared with C".

Semi-concrete suggestion: Suggest using .h headers in codebases which are targeted for sharing at least partially with C, but .hpp or .hh extensions in codebases which are intended for no sharing with C.

eyalroz avatar Aug 17 '22 12:08 eyalroz

The vast majority of header files out there are compatible with C. The better mechanism for declaring that a header should only be used by C++ would be the preprocessor directives - compliments of https://cplusplus.com/doc/tutorial/preprocessor/ and their Error directive (#error) example:

#ifndef __cplusplus
#error A C++ compiler is required!
#endif 

One shouldn't rely on file extensions for that.

NOTE: __cplusplus is common enough among compilers that it should be valid. Others here may have a better check mechanism of that nature but that is the right mechanism for this.

BenjamenMeyer avatar Aug 17 '22 20:08 BenjamenMeyer

@BenjamenMeyer : The vast majority of C++ header files out there are incompatible with C, because most/a lot of the C++ syntax is not valid C syntax, and is not ignored by C compilers. Not sure what you're basing your claim on.

The better mechanism for declaring that a header should only be used by C++ would be the preprocessor directives

You're claiming that header files should artificially pretend to be C-compatible from the outside, then give you an error message when you try to pass them to a C compiler? I don't get it.

Also, few people try to pass C++ headers to C compilers (while the other way around is quite common).

eyalroz avatar Aug 17 '22 21:08 eyalroz

I didn't say simply C++ headers, but headers and I offered a better protection mechanism as well.

Using the #if/#error mechanism is both C and C++ compatible. It's not pretending and it's specifically declaring itself incompatible using language both understand.

BenjamenMeyer avatar Aug 17 '22 22:08 BenjamenMeyer

@BenjamenMeyer : Ah, ok, then I did misunderstand...

But in that case - I'm not sure how your comment is relevant. These are guidelines for writing C++, and the fact that C headers are named .h does not mean that so should C++ headers.

eyalroz avatar Aug 17 '22 22:08 eyalroz

@BenjamenMeyer : Ah, ok, then I did misunderstand...

But in that case - I'm not sure how your comment is relevant. These are guidelines for writing C++, and the fact that C headers are named .h does not mean that so should C++ headers.

It's relevant because you're declaring it's only for C++. There's nothing stopping a C program from importing .hxx, .hpp either but the directives I listed would as it wouldn't allow the program to compile at all. It's good practice to declare it appropriately.

BenjamenMeyer avatar Aug 17 '22 22:08 BenjamenMeyer

A c program can also try to include an arbitrary .txt file, but why should the author of a txt file care? Same, why should the author of a c++ header file actively prevent the inclusion from a c-source file (in addition to writing invalid c code anyway?

At the same time: Why defer the information about what kind of programming language is contained until you (or whatever program - compiler or otherwise) opens and interprets the file (which can be a relatively costly operation)? While not every c++ header file has a .hpp/hxx/hwhatever extension, you can be pretty sure an hpp file is a c++ header file. So an .hpp extension gives me strictly more information than a .h just from looking at the filename. E.g. when globbing, or configuring some basic highlighting rules of an editor based on the file extension.

I'm working quite a bit with mixed c and c++ projects (usually on embedded systems) and I find destinct extensions pretty useful. To e.g. show whats a c++ header and the "equivalent" c wrapper or vice versa.

MikeGitb avatar Aug 18 '22 10:08 MikeGitb

@MikeGitb : So, your last point makes me realize that the same extension is more detrimental than useful in both scenarios: If you don't mix C and C++ then why even think of C, and if you do mix them, it might make it easier but might make it more difficult for you to use the same extension, depending on the specifics of what you do. So in both cases the .h default doesn't quite make sense. With a .hpp (or .hxx or whatever) one at least never mistakes one's C++ headers for anything else.

eyalroz avatar Aug 18 '22 12:08 eyalroz

A c program can also try to include an arbitrary .txt file, but why should the author of a txt file care? Same, why should the author of a c++ header file actively prevent the inclusion from a c-source file (in addition to writing invalid c code anyway?

True; however C++ has a very long history of using the .h extension and it's a valid extension for C++ headers - while .txt and .some.random.extension could be used, they're neither listed as valid C++ header extensions nor do they have a history of being so within the larger community. A guideline should provide for that history and migration. The directives honor that, would only add 3 lines of preprocessor directives to any given header file, and is understandable in both worlds so a proper error is generated instead of leaving the developer to try to figure out why something isn't working as expected - especially when some keywords in C++ are shared and now with C++11 and later have alternate meanings (f.e auto) than their C counterparts.

BenjamenMeyer avatar Aug 18 '22 19:08 BenjamenMeyer

C++ has a very long history of using the .h extension

I don't think so, actually. The standard library headers don't use it. Boost headers don't use it. Few, if any, popular libraries use it (AFAICT).

would only add 3 lines of preprocessor

You keep being hung up on forced inclusion of C++ headers in C program. That is a niche use-case and mostly irrelevant.

eyalroz avatar Aug 18 '22 21:08 eyalroz

@BenjamenMeyer: If you want to do that, sure, add it to your h files, but the much simpler and straight forward solution is to use a different extension (i.e. hpp) which is not going to be included accidentally in c code in the first place. Adding an #idef based compiler error is a mitigation for a problem that - in new projects - need not exist in the first place.

The problem I have with the guideline as is, is that I don't know for what audience it is meant. When working in an existing codebase, I anyway have to use whatever is the convention there. And when I'm not bound by existing convention, then using .h over a c++ specific extension has no benefit.

MikeGitb avatar Aug 18 '22 21:08 MikeGitb

@BenjamenMeyer: If you want to do that, sure, add it to your h files, but the much simpler and straight forward solution is to use a different extension (i.e. hpp) which is not going to be included accidentally in c code in the first place. Adding an #idef based compiler error is a mitigation for a problem that - in new projects - need not exist in the first place.

My point is that the header extension won't do anything. C could still include it; it won't prevent it. So if you're going to make a guideline do something that will actually have a meaningful impact and produce a meaningful error. When I have headers that I want to make sure are only included in C++ I use the directives to generate compiler errors for C code or to remove C++ interfaces and then add appropriate C directives:

#ifndef MY_HEADER__
#define MY_HEADER__

#ifdef __cplusplus
  // C++ specific code or #error <message>
#endif // __cplusplus

extern "C" {
 // C specific code/interfaces
}
#endif //MY_HEADER__

The problem I have with the guideline as is, is that I don't know for what audience it is meant.

I can agree to that.

BenjamenMeyer avatar Aug 18 '22 22:08 BenjamenMeyer

C could still include it;

Sure it could. As I said: It could also include arbitrary text files. But why would c- code try to include e.g. .hpp or .txt files?

Why focus on producing meaningful error when you can effectively prevent the error from happening in the first place? But again: If you have to use the.h extension, then by all means, make sure the error message is readable.

MikeGitb avatar Aug 18 '22 22:08 MikeGitb

@MikeGitb : s/buy/by/ .

@BenjamenMeyer : Please stop with this tangential discussion. This issue regards filenames of C++ headers for C++ programs. Not C. Not C compilers. Not behavior with C compilers.

eyalroz avatar Aug 18 '22 22:08 eyalroz

At the same time: Why defer the information about what kind of programming language is contained until you (or whatever program - compiler or otherwise) opens and interprets the file (which can be a relatively costly operation)? While not every c++ header file has a .hpp/hxx/hwhatever extension, you can be pretty sure an hpp file is a c++ header file. So an .hpp extension gives me strictly more information than a .h just from looking at the filename. E.g. when globbing, or configuring some basic highlighting rules of an editor based on the file extension.

This is the key point here: hpp follows the "shift left" principle - finding errors earlier in the process is cheaper.

bdeeming avatar Aug 18 '22 22:08 bdeeming

@MikeGitb : s/buy/by/ .

@BenjamenMeyer : Please stop with this tangential discussion. This issue regards filenames of C++ headers for C++ programs. Not C. Not C compilers. Not behavior with C compilers.

The original issue had to do with both C and C++, so it is relevant unless you want to close the issue as a whole as irrelevant since as @MikeGitb notes the audience is a little unknown

BenjamenMeyer avatar Aug 18 '22 22:08 BenjamenMeyer

The original issue had to do with both C and C++

No it didn't, and that's my whole point. C++ headers generally have nothing to do with C.

as @MikeGitb notes the audience is a little unknown

The audience which SF.1 as currently stated caters to is perhaps an unknown, and certainly very small. But the core guidelines' audience is better known: It's developers of C++ programs (as opposed to C programs which use C++ headers). These are by far the vast majority of C++ header file authors; hence this issue.

eyalroz avatar Aug 18 '22 23:08 eyalroz

Editors call: We agree this should be a "naming and layout / if you have no better convention already" rule, which is what NL is for. It should be moved to the NL.* naming and layout section.

  • SF.1 should be made NL.27
  • the existing SF.1 section should be retained as empty and redirect to NL.27 (to not break old links)
  • other SF.* rules that mention ".h file" should be reworded to say "header file"

hsutter avatar Sep 22 '22 21:09 hsutter

@hsutter : Well, weakening the rule by moving it to NL is perhaps appropriate, but if you accept the opening argument of this issue at all, then it applies to an NL rule just as well as to an SF rule: The rule should recommend ".hpp if you have no better convention already" - there as well, by the same argument.

eyalroz avatar Sep 22 '22 22:09 eyalroz

@cubbimew : Please read my last comment... the bug is still valid when the recommendation is in the NL section.

eyalroz avatar Sep 23 '22 07:09 eyalroz

@eyalroz I agree with your point but at the call,there was no consensus to choose hpp over other header naming conventions.

cubbimew avatar Sep 23 '22 13:09 cubbimew

@cubbimew : In that case, should the recommendation not have been removed entirely? If there's no consensus regarding whether to recommend .h or .hpp, it seems like neither can be recommended properly.

I'm nitpicking about this because, with what you've described as having happened, it seems like .h will remain recommended just because it's the first idea someone had for a recommendation...

eyalroz avatar Sep 23 '22 14:09 eyalroz