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?
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.