Can I write C++ code without headers (repetitive function declarations)?

Go To StackoverFlow.com

52

Is there any way to not have to write function declarations twice (headers) and still retain the same scalability in compiling, clarity in debugging, and flexibility in design when programming in C++?

2009-06-16 13:55
by thewreck
@nOrd... or modules (n2073) will be finally accepted in the languag - David Rodríguez - dribeas 2011-03-16 10:16


55

Use Lzz. It takes a single file and automatically creates a .h and .cpp for you with all the declarations/definitions in the right place.

Lzz is really very powerful, and handles 99% of full C++ syntax, including templates, specializations etc etc etc.

Update 150120:

Newer C++ '11/14 syntax can only be used within Lzz function bodies.

2009-06-16 14:18
by Richard Corden
+1: Actually, lzz is designed the good way around : as a source language that produces C++ - Steve Schnepp 2009-11-17 09:27


37

I felt the same way when I started writing C, so I also looked into this. The answer is that yes, it's possible and no, you don't want to.

First with the yes.

In GCC, you can do this:

// foo.cph

void foo();

#if __INCLUDE_LEVEL__ == 0
void foo() {
   printf("Hello World!\n");
}
#endif

This has the intended effect: you combine both header and source into one file that can both be included and linked.

Then with the no:

This only works if the compiler has access to the entire source. You can't use this trick when writing a library that you want to distribute but keep closed-source. Either you distribute the full .cph file, or you have to write a separate .h file to go with your .lib. Although maybe you could auto-generate it with the macro preprocessor. It would get hairy though.

And reason #2 why you don't want this, and that's probably the best one: compilation speed. Normally, C sources files only have to be recompiled when the file itself changes, or any of the files it includes changes.

  • The C file can change frequently, but the change only involves recompiling the one file that changed.
  • Header files define interfaces, so they shouldn't change as often. When they do however, they trigger a recompile of every source file that includes them.

When all your files are combined header and source files, every change will trigger a recompile of all source files. C++ isn't known for its fast compile times even now, imagine what would happen when the entire project had to be recompiled every time. Then extrapolate that to a project of hundreds of source files with complicated dependencies...

2009-06-16 14:12
by rix0rrr
Header files work really well in C, I agree with that. But in C++ they don't always make sense. For example, it doesn't make much sense to declare private methods in a class declarations. You should be able to define as much private methods as you wish without affecting outside files - Zelenova 2014-10-07 20:24


27

Sorry, but there's no such thing as a "best practice" for eliminating headers in C++: it's a bad idea, period. If you hate them that much, you have three choices:

  • Become intimately familiar with C++ internals and any compilers you're using; you're going to run into different problems than the average C++ developer, and you'll probably need to solve them without a lot of help.
  • Pick a language you can use "right" without getting depressed
  • Get a tool to generate them for you; you'll still have headers, but you save some typing effort
2009-06-16 14:07
by ojrac
-1 The lzz-tool mentioned in an answer here solves the problems implied by the "asker" without the negative effects you described (as the lzz-tool does use headers. You just don't have to actually write them). That makes this answer unconstructive. sry - 0scar 2009-06-16 18:30
Fair point. I'll acknowledge the 3rd option -- thanks for explaining the flaw - ojrac 2009-06-16 18:51
I think it was probably downvoted because it was nonspecific (what are "hellish problems"? for example) and therefore useless. Moreover, like you noted, it's an opinion and therefore subjective, which is generally unhelpful in this community - weberc2 2013-03-14 16:07
@weberc2 You're totally right -- thanks. I've updated point 1 to be less "fire and brimstone," and more focused on specifics - ojrac 2013-09-27 17:28
@ojrac, No problem. :) I think part of the problem with C++ (header files as well as other things) is that the features all require strict discipline to get them right. For example, if you're not practicing the PIMPL idiom, headers are a pain, but with the PIMPL idiom, they resemble Ada specifications, which are actually valuable. Unlike most languages, C++ pushes you into doing the wrong thing (e.g., publishing private methods in header files) until someone explains the best-practice/workaround--and even then, it's up to you to adhere to them--you'll get no help from the compiler - weberc2 2013-09-27 18:58
Totally. And there's no reason to describe those problems irrationally when there's plenty of useful things to say on the topic - ojrac 2013-09-30 16:02


10

In his article Simple Support for Design by Contract in C++, Pedro Guerreiro stated:

Usually, a C++ class comes in two files: the header file and the definition file. Where should we write the assertions: in the header file, because assertions are specification? Or in the definition file, since they are executable? Or in both, running the risk of inconsistency (and duplicating work)? We recommend, instead, that we forsake the traditional style, and do away with the definition file, using only the header file, as if all functions were defined inline, very much like Java and Eiffel do.

This is such a drastic change from the C++ normality that it risks killing the endeavor at the outset. On the other hand, maintaining two files for each class is so awkward, that sooner or later a C++ development environment will come up that hides that from us, allowing us to concentrate on our classes, without having to worry about where they are stored.

That was 2001. I agreed. It is 2009 now and still no "development environment that hides that from us, allowing us to concentrate on our classes" has come up. Instead, long compile times are the norm.


Note: The link above seems to be dead now. This is the full reference to the publication, as it appears in the Publications section of the author's website:

Pedro Guerreiro, Simple Support for Design by Contract in C++, TOOLS USA 2001, Proceedings, pages 24-34, IEEE, 2001.

2009-06-16 14:10
by Daniel Daranas
In my experience C# compiles faster than C++, and the dependency checking (in VS2008 at least) is much better - Mark Lakata 2013-01-03 01:04
There are lots of such languages that don't require C++ pain. Go being one of my personal favorites - weberc2 2013-03-14 16:12
@MarkLakata - The issue isn't which one compiles all the sources in the system faster. The issue is that if I edit the details of a class implementation, and every class in a large program depends on that class, with C++ I only have to recompile one .cpp file and relink, where with a system with no separation I'd presumably have to recompile everything - T.E.D. 2013-06-04 12:33
@T.E.D. - Yes, that is correct. But Visual Studio compiles a C# library SO much faster than C++, it doesn't really matter. In addition, when you are developing a new application, you are constantly modifying the header files anyways, so you will be compiling a lot, even with C++. I don't have a benchmark to cite, but I estimate C# compilation to be 10-20X faster than C++. In addition Visual studio does C# syntax-compilation in real time (like a spell checker), so you rarely have to hit the compile button until you are finished - Mark Lakata 2013-06-04 17:51
That's why you just build a system that automatically separates things for you. It's 2013. C++ is decades old, and the tools haven't progressed even that much? This is why we are engineers! To automate things - phreakhead 2013-06-15 07:26


8

There is no practical way to get around headers. The only thing you could do is to put all code into one big c++ file. That will end up in an umaintainable mess, so please don't do it.

At the moment C++ header-files are a nessesary evil. I don't like them, but there is no way around them. I'd love to see some improvements and fresh ideas on the problem though.

Btw - once you've got used to it it's not that bad anymore.. C++ (and any other language as well) has more anoying things.

2009-06-16 13:59
by Nils Pipenbrinck
Actually, your "one big c++ file" solution could be decomposed a bit using #includes. These wouldn't have to be "headers" to separately compiled source files (so you could name them .cpp to avoid/facilitate confusion). Its evil IMHO, but I've seen it done - T.E.D. 2013-06-04 12:25


8

What I have seen some people like you do is write everything in the headers. That gives your desired property of only having to write the method profiles once.

Personally I think there are very good reasons why it is better to separate declaration and definition, but if this distresses you there is a way to do what you want.

2009-06-16 14:07
by T.E.D.


5

You have to write function declaration twice, actually (once in header file, once in implementation file). The definition (AKA implementation) of the function will be written once, in the implementation file.

You can write all the code in header files (it is actually a very used practice in generic programming in C++), but this implies that every C/CPP file including that header will imply recompilation of the implementation from those header files.

If you are thinking to a system similar to C# or Java, it is not possible in C++.

2009-06-16 13:59
by Cătălin Pitiș
"this implies that every C/CPP file including that header will imply recompilation of the implementation from those header files." Which is a lesser problem if actually all of your code is in headers, since you'll presumably only have one cpp file to compile. So you'll have one huge compilation, but at least it will only be one. The typical C++ project in header hell has many cpp files, each of which compiles most or all of the header code, for more work in total - Steve Jessop 2009-06-16 14:03
Ok. In priciple you're right. But, if you have hundreds or thousands of translation units, then trying to make them one translation unit (through file inclusion) will be a nightmare. I would never try it this way - Cătălin Pitiș 2009-06-16 14:11
thanks, corrected the mixup with declaration/definition - thewreck 2009-06-16 14:36
@onebyone: but if you write all your code in ehaders and include from a single cpp, then you have only a single translation unit and changing any of the ehaders requires the whole thing to be recompiled while if you properly split the code amongst headers and cpp files, then only the translation units that actually change need to be recompiled - Dan 2009-06-16 14:49
@Dan: Good point. I wonder why I forgot about it. It is the most obvious reason :- - Cătălin Pitiș 2009-06-16 16:04
Absolutely true: scalability is still a problem, and the questioner needs to suck it up and do things "properly", if only in order to learn to play nicely with others. I'm just pointing out that the problem doesn't necessarily bite sooner for one-big-translation-unit than for multiple-TUs. It comes down to how disciplined you are at minimising the headers used by each cpp file. You don't get proper division of dependencies unless you plan for it, and most people (me and most likely the questioner included) get it wrong on the first attempt.. - Steve Jessop 2009-06-16 16:35
I should say that when I said "lesser", I meant compared with other options where every header contains implementation, hence has to include other headers, and everything ends up depending on everything else. I don't mean it's a lesser problem compared with doing it well using the normal means :- - Steve Jessop 2009-06-16 16:45
Ok, really? It's not even possible? This is the future! Every other language can dynamically recompile small parts of the source at a time. How hard is it for the compiler to do some basic file checks and only re-link the file that was changed, after automatically regenerating headers? Java does this all the time. Hell, Android generates Java code from XML FILES all in the background while you're coding - so don't tell me it's impossible in C++. The tools can't still be the same as they were 30 years ago, right - phreakhead 2013-06-15 07:24


5

There's header file generation software. I've never used it, but it might be worth looking into. For instance, check out mkhdr! It supposedly scans C and C++ files and generates the appropriate header files.

(However, as Richard points out, this seems to limit you from using certain C++ functionality. See Richard's answer instead here right in this thread.)

2009-06-16 14:17
by 0scar
I've been using makeheaders for a few years. By now I can't stand to write C code without it; it is much, much better than writing header files and it's a very simple solution. However, it has a bug that breaks some dependency chains; I may get around to fixing it myself someday. Not sure if it really works for templates or not since I use it for C - Nate C-K 2015-03-05 20:02


3

Actually... You can write the entire implementation in a file. Templated classes are all defined in the header file with no cpp file.

You can also save then with whatever extensions you want. Then in #include statements, you would include your file.

/* mycode.cpp */
#pragma once
#include <iostreams.h>

class myclass {
public:
  myclass();

  dothing();
};

myclass::myclass() { }
myclass::dothing()
{
  // code
}

Then in another file

/* myothercode.cpp */
#pragma once
#include "mycode.cpp"

int main() {
   myclass A;
   A.dothing();
   return 0;
}

You may need to setup some build rules, but it should work.

2009-06-16 14:03
by Kieveli
I gotta add... The biggest rule for coding is to make it easy for others to read. So C++ people wouldn't know what the hell is going on. This isn't recommended, but it's possible ; - Kieveli 2009-06-16 14:07
Also, the OP asked about scalability of compiling, which this would definitely impact - Lou Franco 2009-06-16 14:10
>including a .cpp file will definitely get the maintenance programmers on your case (In a bad way). - C Johnson 2010-08-07 10:12


3

Nobody has mentioned Visual-Assist X under Visual Studio 2012 yet.

It has a bunch of menus and hotkeys that you can use to ease the pain of maintaining headers:

  • "Create Declaration" copies the function declaration from the current function into the .hpp file.
  • "Refactor..Change signature" allows you to simultaneously update the .cpp and .h file with one command.
  • Alt-O allows you to instantly flip between .cpp and .h file.
2013-06-01 14:48
by Contango


2

You can avoid headers. Completely. But I don't recommend it.

You'll be faced with some very specific limitations. One of them is you won't be able to have circular references (you won't be able to have class Parent contain a pointer to an instance of class ChildNode, and class ChildNode also contain a pointer to an instance of class Parent. It'd have to be one or the other.)

There are other limitations which just end up making your code really weird. Stick to headers. You'll learn to actually like them (since they provide a nice quick synopsis of what a class can do).

2009-06-16 14:26
by bobobobo
"Header files" are basically a preprocessor trick. You can do forward references in C++ without them - T.E.D. 2013-06-04 12:24
But they're a necessary preprocessor trick -- you could not use circular references properly without them (problems with incomplete types). C would have been deficient and the standard would have probably been changed - bobobobo 2013-06-04 12:26
No they aren't. You can use forward class references directly in a single .cpp file without involving the preprocessor at all - T.E.D. 2013-06-04 15:12
Oh, I see what you're saying. Yes you could just type out the prototype of one class, implement the second class, then implement the first class below that. It wouldn't be very neat, but it could be done - bobobobo 2013-06-05 20:39
class a; class b {a * ref;}; class a {b * ref;};T.E.D. 2013-06-05 22:53
Illegal: struct a ; struct b { a *r; b(){ r->go(); } void go(){} } ; struct a { b *r; a(){ r->go(); } void go(){} } ; member access into incomplete type 'a'. Legal: struct b2 ; struct a2 { b2 *r; a2(); void go(); } ; struct b2 { a2 *r ; b2(){ r->go(); } void go(){} } ; a2::a2(){ r->go(); } void a2::go(){}bobobobo 2013-06-06 14:58


2

To offer a variant on the popular answer of rix0rrr:

// foo.cph

#define INCLUDEMODE
#include "foo.cph"
#include "other.cph"
#undef INCLUDEMODE

void foo()
#if !defined(INCLUDEMODE)
{
   printf("Hello World!\n");
}
#else
;
#endif

void bar()
#if !defined(INCLUDEMODE)
{
    foo();
}
#else
;
#endif

I do not recommend this, bit I think this construction demonstrates the removal of content repetition at the cost of rote repetition. I guess it makes copy-pasta easier? That's not really a virtue.

As with all the other tricks of this nature, a modification to the body of a function will still require recompilation of all files including the file containing that function. Very careful automated tools can partially avoid this, but they would still have to parse the source file to check, and be carefully constructed to not rewrite their output if it's no different.

For other readers: I spent a few minutes trying to figure out include guards in this format, but didn't come up with anything good. Comments?

2009-06-17 03:52
by Phil Miller
If you are pursuing that path, I wonder whether DECLARE and DEFINITION macros could be used: DECLARE( void foo() )\nDEFINE({\n....\n}) where in inclusion mode DECLARE adds a ; and DEFINE resolves to nothing... Maybe more readable, even if I would not recommend it (and is just syntactic sugar, all the same problems are still there - David Rodríguez - dribeas 2011-03-16 10:46


2

After reading all the other answers, I find it missing that there is ongoing work to add support for modules in the C++ standard. It will not make it to C++0x, but the intention is that it will be tackled in a later Technical Review (rather than waiting for a new standard, that will take ages).

The proposal that was being discussed is N2073.

The bad part of it is that you will not get that, not even with the newest c++0x compilers. You will have to wait. In the mean time, you will have to compromise between the uniqueness of definitions in header-only libraries and the cost of compilation.

2011-03-16 10:51
by David Rodríguez - dribeas


1

As far as I know, no. Headers are an inherent part of C++ as a language. Don't forget that forward declaration allows the compiler to merely include a function pointer to a compiled object/function without having to include the whole function (which you can get around by declaring a function inline (if the compiler feels like it).

If you really, really, really hate making headers, write a perl-script to autogenerate them, instead. I'm not sure I'd recommend it though.

2009-06-16 14:02
by mikek


1

I understand your problems. I would say that the C++ main problem is the compilation/build method that it inherited from the C. The C/C++ header structure has been designed in times when coding involved less definitions and more implementations. Don't throw bottles on me, but that's how it looks like.

Since then the OOP has conquered the world and the world is more about definitions then implementations. As the result, including headers makes pretty painful to work with a language where the fundamental collections such as the ones in the STL made with templates which are notoriously difficult job for the compiler to deal with. All those magic with the precompiled headers doesn't help so much when it comes to TDD, refactoring tools, the general development environment.

Of course C programmers are not suffering from this too much since they don't have compiler-heavy header files and so they are happy with the pretty straightforward, low-level compilation tool chain. With C++ this is a history of suffering: endless forward declarations, precompiled headers, external parsers, custom preprocessors etc.

Many people, however, does not realize that the C++ is the ONLY language that has strong and modern solutions for high- and low-level problems. It's easy to say that you should go for an other language with proper reflection and build system, but it is non-sense that we have to sacrifice the low-level programming solutions with that and we need to complicate things with low-level language mixed with some virtual-machine/JIT based solution.

I have this idea for some time now, that it would be the most cool thing on earth to have a "unit" based c++ tool-chain, similar to that in D. The problem comes up with the cross-platform part: the object files are able to store any information, no problem with that, but since on windows the object file's structure is different that of the ELF, it would be pain in the ass to implement a cross-platform solution to store and process the half-way-compilation units.

2010-09-14 10:58
by progician
There is (actually was and will be, they are not really doing it now) work on a module system for c++ n2073 that was dropped from C++0x (was) to be tackled in a Technical Review (will be) - David Rodríguez - dribeas 2011-03-16 10:43
I'm aware of that proposal, but it seems quite unlikely to me it gets implemented anytime soon but I wish it was! Getting to the root of the problem is that this would be the biggest architecture change in the history of C++: The existing code base (definition inclusion based code) would be mixed with module based compilation units and that will complicate things quite a bit. Cross-fingers for the proposal though - progician 2011-04-26 09:30


1

It's completely possible to develop without header files. One can include a source file directly:

#include "MyModule.c"

The major issue with this is one of circular dependencies (ie: in C you must declare a function before calling it). This is not an issue if you design your code completely top-down, but it can take some time to wrap ones head around this sort of design pattern if you're not used to it.

If you absolutely must have circular dependencies, one may want to consider creating a file specifically for declarations and including it before everything else. This is a little inconvenient, but still less pollution than having a header for every C file.

I am currently developing using this method for one of my major projects. Here is a breakdown of advantages I've experienced:

  • Much less file pollution in your source tree.
  • Faster build times. (Only one object file is produced by the compiler, main.o)
  • Simpler make files. (Only one object file is produced by the compiler, main.o)
  • No need to "make clean". Every build is "clean".
  • Less boiler plate code. Less code = less potential bugs.

I've discovered that Gish (a game by Cryptic Sea, Edmund McMillen) used a variation on this technique inside its own source code.

2011-03-16 08:19
by Nathaniel Sabanski
Including files with .c extension cannot be said to be header-less, but rather header-only (each translation unit that needs that code includes it, so the behavior is that of header-only libraries - David Rodríguez - dribeas 2011-03-16 10:47
It's all semantics. At the core level, #include just inserts the specified file at that line - Nathaniel Sabanski 2011-03-17 01:52


0

You can carefully lay out your functions so that all of the dependent functions are compiled after their dependencies, but as Nils implied, that is not practical.

Catalin (forgive the missing diacritical marks) also suggested a more practical alternative of defining your methods in the header files. This can actually work in most cases.. especially if you have guards in your header files to make sure they are only included once.

I personally think that header files + declaring functions is much more desirable for 'getting your head around' new code, but that is a personal preference I suppose...

2009-06-16 14:03
by John Weldon


0

You can do without headers. But, why spend effort trying to avoid carefully worked out best practices that have been developed over many years by experts.

When I wrote basic, I quite liked line numbers. But, I wouldn't think of trying to jam them into C++, because that's not the C++ way. The same goes for headers... and I'm sure other answers explain all the reasoning.

2009-06-16 14:17
by Scott Langham


0

For practical purposes no, it's not possible. Technically, yes, you can. But, frankly, it's an abuse of the language, and you should adapt to the language. Or move to something like C#.

2009-06-16 14:17
by Paul Nathan


0

It is best practice to use the header files, and after a while it will grow into you. I agree that having only one file is easier, but It also can leed to bad codeing.

some of these things, althoug feel awkward, allow you to get more then meets the eye.

as an example think about pointers, passing parameters by value/by reference... etc.

for me the header files allow-me to keep my projects properly structured

2009-06-16 15:40
by NoName


0

Learn to recognize that header files are a good thing. They separate how codes appears to another user from the implementation of how it actually performs its operations.

When I use someone's code I do now want to have to wade through all of the implementation to see what the methods are on a class. I care about what the code does, not how it does it.

2009-06-21 17:37
by Richard


0

This has been "revived" thanks to a duplicate...

In any case, the concept of a header is a worthy one, i.e. separate out the interface from the implementation detail. The header outlines how you use a class / method, and not how it does it.

The downside is the detail within headers and all the workarounds necessary. These are the main issues as I see them:

  • dependency generation. When a header is modified, any source file that includes this header requires recompilation. The issue is of course working out which source files actually use it. When a "clean" build is performed it is often necessary to cache the information in some kind of dependency tree for later.

  • include guards. Ok, we all know how to write these but in a perfect system it would not be necessary.

  • private details. Within a class, you must put the private details into the header. Yes, the compiler needs to know the "size" of the class, but in a perfect system it would be able to bind this in a later phase. This leads to all kinds of workaround like pImpl and using abstract base classes even when you only have one implementation just because you want to hide a dependency.

The perfect system would work with

  • separate class definition and declaration
  • A clear bind between these two so the compiler would know where a class declaration and its definition are, and would know what the size of a class.
  • You declare using class rather than pre-processor #include. The compiler knows where to find a class. Once you have done "using class" you can use that class name without qualifying it.

I'd be interested to know how D does it.

With regards to whether you can use C++ without headers, I would say no you need them for abstract base classes and standard library. Aside from that you could get by without them, although you probably would not want to.

2011-03-16 11:47
by CashCow
In D there's a module system which means there's no real separation between the implementation and the definition (the same way as in java). The only down-side of such a solution that you can not distribute the public-only definitions as kind of a reference... but heck, we've doxygen (ddoc in the case of D) for doing that job :D I'm not so sure though that the D build process using the modules in their half-way compiled manner (that is, using some sort of binary interface definition in the object files themselves... if it does that's a killer feature! - progician 2011-06-15 13:15
Found it, the DMD compiler have a feature to extract the D interface to a separate file (-H switch). http://www.digitalmars.com/d/2.0/dmd-windows.html#interface_files This is one of the most important features that is missing in C++ modules+module interfaces - progician 2011-06-15 13:22
Ads