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

Viewed 49115

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++?

25 Answers

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.

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...

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

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.

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.

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.

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.)

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++.

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.

C++ 20 modules solve this problem. There is no need for copy-pasting anymore! Just write your code in a single file and export things using "export".

export module mymodule;

export int myfunc() {
    return 1
}

Read more about modules here: https://en.cppreference.com/w/cpp/language/modules

At the time of writing this answer (2022 Feb), these compilers support it: module support

See here for the supported compilers: https://en.cppreference.com/w/cpp/compiler_support

See this answer if you want to use modules with CMake: https://stackoverflow.com/a/71119196/7910299

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).

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?

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.

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...

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.

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#.

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

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.

Can I write C++ code without headers

Read more about C++, e.g. the Programming using C++ book then the C+11 standard n3337.

Yes, because the preprocessor is (conceptually) generating code without headers.

If your C++ compiler is GCC and you are compiling your translation unit foo.cc consider running g++ -O -Wall -Wextra -C -E foo.cc > foo.ii; the emitted file foo.ii does not contain any preprocessor directive, and could be compiled with g++ -O foo.ii -o foo-bin into a foo-bin executable (at least on Linux). See also Advanced Linux Programming

On Linux, the following C++ file

// file ex.cc
extern "C" long write(int fd, const void *buf, size_t count);
extern "C" long strlen(const char*);
extern "C" void perror(const char*);
int main (int argc, char**argv)
{
   if (argc>1) 
     write(1, argv[1], strlen(argv[1]);
   else 
     write(1, __FILE__ " has no argument",
              sizeof(__FILE__ " has no argument"));
   if (write(1, "\n", 1) <= 0) {
     perror(__FILE__);
     return 1;
   }
   return 0;
}

could be compiled using GCC as g++ ex.cc -O ex-bin into an executable ex-bin which, when executed, would show something.

In some cases, it is worthwhile to generate some C++ code with another program

(perhaps SWIG, ANTLR, Bison, RefPerSys, GPP, or your own C++ code generator) and configure your build automation tool (e.g. ninja-build or GNU make) to handle such a situation. Notice that the source code of GCC 10 has a dozen of C++ code generators.

With GCC, you might sometimes consider writing your own GCC plugin to analyze your (or others) C++ code (e.g. at the GIMPLE level). See also (in fall 2020) CHARIOT and DECODER European projects. You could also consider using the Clang static analyzer or Frama-C++.

Historically hearder files have been used for two reasons.

  1. To provides symbols when compiling a program that wants to used a library or a additional file.

  2. To hide part of the implementing; keep things private.

For example say you have a function you don't want exposed to other parts of your program, but want to use in your implementation. In that case, you would write the function in the CPP file, but leave it out of the header file. You can do this with variables and anything that would want to keep private in the impregnation that you don't want exposed to conumbers of that source code. In other programming lanugases there is a "public" keyword that allows module parts to be kept from being exposed to other parts of your program. In C and C++ no such facility exists at afile level, so header files are used intead.

Header files are not perfect. Useing '#include' just copies the contents of what ever file you provide. Single quotes for the current working tree and < and > for system installed headers. In CPP for system installed std components the '.h' is omitted; just another way C++ likes to do its own thing. If you want to give '#include' any kind of file, it will be included. It really isn't a module system like Java, Python, and most other programming lanuages have. Since headers are not modules some extra steps need to be taken to get similar function out of them. The Prepossesser (the thing that works with all the #keywords) will blindly include what every you state is needed to be consumed in that file, but C or C++ want to have your symbals or implications defined only one in compilation. If you use a library, no it main.cpp, but in the two files that main includes, then you only want that library included once and not twice. Standard Library components are handled special, so you don't need to worry about using the same C++ include everywhere. To make it so that the first time the Prepossesser sees your library it doesn't include it again, you need to use a heard guard.

A heard guard is the simplest thing. It looks like this:

#ifndef LIBRARY_H #define LIBRARY_H

// Write your definitions here.

#endif

It is considered good to comment the ifndef like this:

#endif // LIBRARY_H

But if you don't do the comment the compiler wont care and it wont hurt anthing.

All #ifndef is doing is checking whether LIBRARY_H is equal to 0; undefined. When LIBRARY_H is 0, it provides what comes before the #endif.

Then #define LIBRARY_H sets LIBRARY_H to 1, so the next time the Preprocessor sees #ifndef LIBRARY_H, it wont provide the same contents again.

(LIBRARY_H should be what ever the file name is and then _ and the extension. This is not going break anything if you don't write the same thing, but you should be consistent. At least put the file name for the #ifndef. Otherwise it might get confusing what guards are for what.)

Really nothing fancy going on here.


Now you don't want to use header files.

Great, say you don't care about:

  • Having things private by excluding them from header files

  • You don't intend to used this code in a library. If you ever do, it may be easier to go with headers now so you don't have to reorganise your code into headers later.

  • You don't want to repeat yourself once in a header file and then in a C++ file.

The purpose of hearder files can seem ambiguous and if you don't care about people telling out it's wrong for imaginary reasons, then save your hands and don't bother repeating yourself.

How to include only hearder files

Do

#ifndef THING_CPP
#define THING_CPP

#include <iostream>

void drink_me() {
  std::cout << "Drink me!" << std::endl;
}

#endif  // THING_CPP

for thing.cpp.

And for main.cpp do

#include "thing.cpp"

int main() {
  drink_me();
  return 0;
}

then compile.

Basically just name your included CPP file with the CPP extension and then treat it like a header file but write out the implementations in that one file.

Related