Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Header-only libraries and multiple definition errors

Tags:

I want to write a library that to use, you only need to include one header file. However, if you have multiple source files and include the header in both, you'll get multiple definition errors, because the library is both declared and defined in the header. I have seen header-only libraries, in Boost I think. How did they do that?

like image 610
Epro Avatar asked Oct 19 '10 22:10

Epro


People also ask

How do you avoid multiple definitions in C++?

You'd create a header that defines the type and declares the objects, something like: using Plane = /* however you want to define a plane */; extern Plane ground; , then a single . cpp file that includes that header, and defines the plane for the ground: #include "ground.

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.

What means header-only library?

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.

Can you put definitions in header files?

Because a header file might potentially be included by multiple files, it cannot contain definitions that might produce multiple definitions of the same name. The following are not allowed, or are considered very bad practice: built-in type definitions at namespace or global scope.


2 Answers

Declare your functions inline, and put them in a namespace so you don't collide:

namespace fancy_schmancy {   inline void my_fn()   {     // magic happens   } }; 
like image 149
John Dibling Avatar answered Sep 19 '22 18:09

John Dibling


The main reason why Boost is largely header-only is because it's heavily template oriented. Templates generally get a pass from the one definition rule. In fact to effectively use templates, you must have the definition visible in any translation unit that uses the template.

Another way around the one definition rule (ODR) is to use inline functions. Actually, getting a free-pass from the ODR is what inline really does - the fact that it might inline the function is really more of an optional side-effect.

A final option (but probably not as good) is to make your functions static. This may lead to code bloat if the linker isn't able to figure out that all those function instances are really the same. But I mention it for completeness. Note that compilers will often inline static functions even if they aren't marked as inline.

like image 43
Michael Burr Avatar answered Sep 22 '22 18:09

Michael Burr