How do I create a header-only library?
Asked Answered
S

4

55

I'd like to package a library I'm working on as a header-only library to make it easier for clients to use. (It's small and there's really no reason to put it into a separate translation unit) However, I cannot simply put my code in headers because this violates C++'s one definition rule. (Assuming that the library header is included in multiple translation units of a client project)

How does one modify a library to make it header-only?

Scribe answered 8/2, 2010 at 22:39 Comment(0)
W
87

You can use the inline keyword:

// header.hpp (included into multiple translation units)

void foo_bad() {} // multiple definitions, one in every translation unit :(

inline void foo_good() {} // ok :)

inline allows the linker to simply pick one definition and discard the rest.

(As such, if those definitions don't actually match, you get a good dose of undefined behavior...!)


As an aside, member functions defined within a class-type, are implicitly marked inline:

struct myclass
{
    void i_am_inline_implicitly()
    {
        // because my definition is here
    }

    void but_i_am_not();
    void neither_am_i();
};

inline void myclass::but_i_am_not()
{
    // but that doesn't mean my definition cannot be explicitly inline
}

void myclass::neither_am_i()
{
    // but in this case, no inline for me :(
}
Woebegone answered 8/2, 2010 at 22:41 Comment(8)
+1 from me. This is pretty much all inline means to modern compilers.Pich
Interesting -- I don't have to mark them as inline in the class definition, only at the member functions' definition?Scribe
@BillyONeal: Yup. If the member function is defined within the class definition, it's inline. Outside, the rules of a regular function apply.Woebegone
@GManNickG: No, I mean myclass::but_i_am_not -- it isn't marked inline when it is declared in the class definition.Scribe
@BillyONeal: Oh, yup. It only matters on the definition. I believe putting it on the declaration will implicitly make all definitions inline as well.Woebegone
@Woebegone If I inline every function, will the compiler will replace every function call to the function body?Rhone
@gil123: No. In C++, inline esseentially no longer has anything at all to do with the actual optimization technique of inlining, that's entirely up to the compiler. It just means "if you see this function definition more than once, assume they are the same and pick one". Without inline, it would be a duplicate definition error.Woebegone
Is it bad practice to explicitly mark defined member functions as inline? (If they would already implicitly be inline)Nyctalopia
P
12

Use header guards as Liz suggests and don't forget to put "inline" before your function methods.

ie

#ifndef MY_HEADER_H_
#define MY_HEADER_H_

inline RetType FunctionName( ParamType1 param1, ParamType2 param2 )
{
    // Function body
    return retType;
}

#endif
Polycrates answered 8/2, 2010 at 22:41 Comment(2)
Nitpick: In C++, there is no such thing as a method. There are member functions and nonmember functions.Scribe
@BillyONeal That's not true; as you can read in Stroustrups "The C++ Programming Language" on page 587, virtual member functions are "sometimes called methods".Kassiekassity
R
5

Also, I think you'll need to avoid any use of global variables or static variables in your header-only-library code.

Realism answered 8/2, 2010 at 22:41 Comment(0)
S
-3

Use header guards for the parts that compile in one place.

Steiermark answered 8/2, 2010 at 22:40 Comment(5)
@GMan: What more do you need?Plumage
Well I don't know about you; but my projects consist of more than one file.Woebegone
I'm already using header guards (actually #pragma once) -- the issue isn't that the header is being included more than once, it's that I have more than one .cpp file in the project using the library.Scribe
@Billy: By the way, pragma once once is only widely supported, not standard.Woebegone
Yes -- only need to support msvcc for this particular project.Scribe

© 2022 - 2024 — McMap. All rights reserved.