Search code examples
c++inlineheader-files

When should a function be inline or not?


Say I have the following class declared in a header file, with a friend function swap:

// header.h
class myClass
{
    friend void swap(myClass &, myClass &);

public:
    myClass(int ii = 0) : i(ii) {}

private:
    int i;
};

Now I want to define swap. If I define it later in the same header file like this,

inline void swap(myClass &a, myClass &b)
{
    using std::swap;
    swap(a.i, b.i);
}

everything is fine. But if I remove the inline specifier, I get an error.

Now say I want to define swap in a separate implementation file instead. If I define it like this,

// impl.cc
#include "header.h"
void swap(myClass &a, myClass &b)
{
    using std::swap;
    swap(a.i, b.i);
}

everything is fine. But now if I add the inline specifier, I get an error.

Why does one version need inline but the other version can't have it?


Solution

  • From the C++ Standard (9.1.6 The inline specifier)

    6 If an inline function or variable is odr-used in a translation unit, a definition of it shall be reachable from the end of that translation unit, and it shall have exactly the same definition in every such translation unit (6.2). [Note: A call to the inline function or a use of the inline variable may be encountered before its definition appears in the translation unit. —end note] If a definition of a function or variable is reachable at the point of its first declaration as inline, the program is ill-formed. If a function or variable with external or module linkage is declared inline in one translation unit, there shall be a reachable inline declaration in all translation units in which it is declared; no diagnostic is required. An inline function or variable with external or module linkage shall have the same address in all translation units. [Note: A static local variable in an inline function with external or module linkage always refers to the same object. A type defined within the body of an inline function with external or module linkage is the same type in every translation unit. —end note]

    So either you declare the friend function as an inline function in a header such a way that its definition is reachable in each translation unit where it is used. Or the function is a non-inline function and its definition shall be placed in one compilation unit to satisfy the One Definition Rule.