Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it ever impossible to write a header-only library?

Is there ever such a pattern of dependancies that it is impossible to keep everything in header files only? What if we enforced a rule of one class per header only?

For the purposes of this question, let's ignore static things :)

like image 621
sooniln Avatar asked Sep 20 '10 17:09

sooniln


People also ask

Are header-only libraries good?

For example, header-only libraries sometimes increase code size & compilation times. "Having a header-only library also means you don't have to worry about different platforms where the library might be used": only if you don't have to maintain the library.

How do header-only libraries work?

In the context of the C or C++ programming languages, a library is called header-only if the full definitions of all macros, functions and classes comprising the library are visible to the compiler in a header file form.

Is a header file a library?

No. Header File is the file where all the headers name are mentioned that going to be used or consumed in the main code file. On other hand Library is the file where the implementation code of each header is written down which is mentioned in the Header file.

How many header files are there?

There are a total of 49 header files in the Standard C++ Library. This includes equivalents of the 19 Standard C Library header files. All of the equivalent C header files have a 'c' prepended to the name and have no . h file extension.


3 Answers

I am aware of no features in standard C++, excepting statics which you have already mentioned, which require a library to define a full translation unit (instead of only headers). However, it's not recommended to do that, because when you do, you force all your clients to recompile their entire codebase whenever your library changes. If you're using source files or a static library or a dynamic library form of distribution, your library can be changed/updated/modified without forcing everyone to recompile.

like image 121
Billy ONeal Avatar answered Oct 10 '22 14:10

Billy ONeal


It is possible, I would say, at the express condition of not using a number of language features: as you noticed, a few uses of the static keyword.

It may require a few trick, but they can be reviewed.

  1. You'll need to keep the header / source distinction whenever you need to break a dependency cycle, even though the two files will be header files in practice.
  2. Free-functions (non-template) have to be declared inline, the compiler may not inline them, but if they are declared so it won't complained that they have been redefined when the client builts its library / executable.
  3. Globally shared data (global variables and class static attributes) should be emulated using local static attribute in functions / class methods. In practice it matters little as far as the caller is concerned (just adds ()). Note that in C++0x this becomes the favored way because it's guaranteed to be thread-safe while still protecting from the initialization order fiasco, until then... it's not thread-safe ;)

Respecting those 3 points, I believe you would be able to write a fully-fledged header-only library (anyone sees something else I missed ?)

A number of Boost Libraries have used similar tricks to be header-only even though their code was not completely template. For example Asio does very consciously and proposes the alternative using flags (see release notes for Asio 1.4.6):

  • clients who only need a couple features need not worry about building / linking, they just grab what they need
  • clients who rely on it a bit more or want to cut down on compilation time are offered the ability to build their own Asio library (with their own sets of flags) and then include "lightweight" headers

This way (at the price of some more effort on the part of the library devs) the clients get their cake and eat it too. It's a pretty nice solution I think.

Note: I am wondering whether static functions could be inlined, I prefer to use anonymous namespaces myself so never really looked into it...

like image 42
Matthieu M. Avatar answered Oct 10 '22 13:10

Matthieu M.


The one class per header rule is meaningless. If this doesn't work:

#include <header1>
#include <header2>

then some variation of this will:

#include <header1a>
#include <header2>
#include <header1b>

This might result in less than one class per header, but you can always use (void*) and casts and inline functions (in which case the 'inline' will likely be duly ignored by the compiler). So the question, seems to me, can be reduced to:

class A
{
// ...
void *pimpl;
}

Is it possible that the private implementation, pimpl, depends on the declaration of A? If so then pimpl.cpp (as a header) must both precede and follow A.h. But Since you can always, once again, use (void*) and casts and inline functions in preceding headers, it can be done.

Of course, I could be wrong. In either case: Ick.

like image 2
paul Avatar answered Oct 10 '22 13:10

paul