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?

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552

4 Answers4

86

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 :(
}
GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 7
    +1 from me. This is pretty much all inline means to modern compilers. – Charles Beattie Feb 08 '10 at 23:22
  • Interesting -- I don't have to mark them as inline in the class definition, only at the member functions' definition? – Billy ONeal Jun 07 '13 at 21:31
  • @BillyONeal: Yup. If the member function is defined within the class definition, it's `inline`. Outside, the rules of a regular function apply. – GManNickG Jun 07 '13 at 21:37
  • @GManNickG: No, I mean `myclass::but_i_am_not` -- it isn't marked inline when it is declared in the class definition. – Billy ONeal Jun 07 '13 at 21:39
  • @BillyONeal: Oh, yup. It only matters on the definition. I believe putting it on the declaration will implicitly make all definitions `inline` as well. – GManNickG Jun 07 '13 at 22:02
  • @GManNickG If I inline every function, will the compiler will replace every function call to the function body? – gil123 Apr 13 '19 at 14:17
  • 3
    @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. – GManNickG Apr 13 '19 at 17:18
  • Is it bad practice to explicitly mark defined member functions as inline? (If they would already implicitly be inline) – Nathan29006781 Sep 14 '22 at 19:20
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
Goz
  • 61,365
  • 24
  • 124
  • 204
  • 3
    Nitpick: In C++, there is no such thing as a method. There are member functions and nonmember functions. – Billy ONeal Jun 07 '13 at 21:30
  • 14
    @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". – Philipp Ludwig Mar 26 '17 at 11:33
5

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

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
-3

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

Liz Albin
  • 1,479
  • 8
  • 8