Inline functions – what are they exactly vis-a-vis the inline keyword?

Maybe a few examples would help.

1. Traditional compiled library

foo.h:

extern int x;
int * f();

foo.cpp:

#include "foo.h"

int x = 25;

int * f() { return &x; }

Users include foo.h and need to link in the translation unit containing foo.cpp in order to call f. Every such call returns the same address.

2. Separate, TU-local variables

foo.h:

static int x = 35;
static int * f() { return &x; }

Every TU that includes foo.h gets a separate and distinct function f, calling which results in a unique value per TU.

3. Baby’s first ODR violation

foo.h:

static int x = 45;
inline int * f() { return &x; }

This appears to be a header-only library, but if foo.h is included in more than one TU, this constitutes an ODR violation, since f would be defined more than once but not all of its definitions would be identical.

This is a common mistake. Workarounds include things like making x a template or replacing x with a function like int & x() { static int impl = 45; return impl; }. Note that if you omit the static, you would most likely get a linker error because of multiple definitions of x; static seemingly “makes the code compile”.

4. C++17 to the rescue: Proper header-only libraries

foo.h:

inline int x = 55;
inline int * f() { return &x; }

This version is functionally equivalent to (1), but does not require a dedicated translation unit to contain the definitions of x and f.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)