Reputation: 1926
I was reading ODR and as the rule says "In the entire program, an object or non-inline function cannot have more than one definition"
and I tried the following...
file1.cpp
#include <iostream>
using namespace std;
inline int func1(void){ return 5; }
inline int func2(void){ return 6; }
inline int func3(void){ return 7; }
int sum(void);
int main(int argc, char *argv[])
{
cout << func1() << endl;
cout << func2() << endl;
cout << func3() << endl;
cout << sum() << endl;
return 0;
}
file2.cpp
inline int func1(void) { return 5; }
inline int func2(void) { return 6; }
inline int func3(void) { return 7; }
int sum(void) { return func1() + func2() + func3(); }
It worked as the rule says. I can have multiple definition of inline functions.
Upvotes: 19
Views: 4641
Reputation: 39658
What is the difference between non-inline function linkage and inline function linkage?
There is none; see [dcl.inline] note 1
The
inline
keyword has no effect on the linkage of a function.
However, inline
results in a relaxation of the one-definition-rule (ODR):
For any definable item
D
with definitions in multiple translation units,
- if
D
is a non-inline non-templated function or variable, or- if the definitions in different translation units do not satisfy the following requirements,
the program is ill-formed; [...]
In other words, it is possible for an inline function to be defined in multiple translation units (i.e. .cpp
files) without getting a linker error.
This works because the linker chooses one definition and ignores all others.
In other words, an inline function is a weak symbol.
However, [basic.def.odr] defines heavy restrictions. Namely, an inline function needs to be defined exactly the same, token by token, everywhere. For example:
// a.cpp
inline int foo() { return 0; }
// b.cpp
inline long foo() { return 0; }
Such a program is ill-formed, no diagnostic required because the definitions are not identical.
The easiest way to ensure that all definitions are identical is by putting them in a header.
Headers are copied and pasted into translation units with #include
, making it much less likely that you've messed up. See also Why do inline functions have to be defined in a header file?
The compiler will inline functions as an optimization regardless whether inline
was used or not.
As long as a definition of the function is visible to the compiler, it will perform this optimization.
inline
merely provides a hint which contributes to the heuristic which decides whether inlining should take place.
See also: Are the "inline" keyword and "inlining" optimization separate concepts?
Upvotes: 2
Reputation: 76317
Making a function inline
does two things (the second point is more relevant to your question):
It is a suggestion by the programmer to the compiler, to make calls to this function fast, possibly by doing inline expansion. Roughly, inline expansion is similar to treating the inline function like a macro, expanding each call to it, by the code of its body. This is a suggestion - the compiler may not (and sometimes cannot) perform various optimizations like that.
It specifies the scope of the function to be that of a translation unit. So, if an inline
function appears in foo.cpp
(either because it was written in it, or because it #include
s a header in which it was written, in which case the preprocessor basically makes it so). Now you compile foo.cpp
, and possibly also some other bar.cpp
which also contains an inline
function with the same signature (possibly the exact same one; probably due to both #include
ing the same header). When the linker links the two object files, it will not be considered a violation of the ODR, as the inline
directive made each copy of the file local to its translation unit (the object file created by compiling it, effectively). This is not a suggestion, it is binding.
It is not coincidental that these two things go together. The most common case is for an inline
function to appear in a header #include
d by several source files, probably because the programmer wanted to request fast inline expansion. This requires the translation-unit locality rule, though, so that linker errors shouldn't arise.
Upvotes: 21