I'm trying to extern an inline function.
There is no reason to use extern
with a function. See storage duration - linkage. Functions have external linkage by default; in order to not have external linkage, something special needs to be done (i.e. put it in an anonymous namespace or declare it static
). So the normal use of an inline function already exhibits external linkage with no need for the extern
keyword.
How I thought it should work:
//a.cpp
inline void f(int) {}
//b.cpp
extern void f(int);
int main() { f(4); }
Then by reading this ("1) It must be declared inline
in every translation unit.").
That reference is correct, but look up a bit more where it says "The definition of an inline function [...] must be present in the translation unit where it is accessed [...]." Your example has a declaration of f
in b.cpp
, but not a definition. If you are going to call f
from b.cpp
, you need the full definition in that translation unit, as in:
inline void f(int) {}
(This is the same code that exists in a.cpp
.) If you leave off the curly braces, then you have a declaration but not a definition, making it illegal to call f
from that translation unit.
Basically, it is a real pain to define an inline function outside a header file, unless you give it internal linkage. That's because each source file that uses the inline function would need its own copy of the function body, meaning that if you change the function, you need to make that change in multiple files. Oof. Don't do it. Define each of your inline
functions in a header file. If you think you want to define one in a source file, you probably misunderstand what "inline
" means.
What does "inline
" mean?
As far as the compiler is concerned, the inline
keyword means (almost) nothing. It is just a flag on a function definition that gets propagated into the object code so that the linker sees it. The compiler processes the function just as it would any other function. The function may be called normally, or calls to it might be inlined – just like any other function.
The one case where the compiler might do something with the inline
flag is when a function is declared inline
, is used, but lacks a definition. This is an error that can be caught before the linker takes over. It does not have to be caught by the compiler, but it can be. (If not caught by the compiler, it would be caught by the linker.)
Moving on to the linking stage. When the linker sees the inline
flag, it suspends the one-definition rule for that function. The linker will expect to see a definition of the function in each translation unit that still uses the function after the compiler's optimizations. It gets to choose any one of those definitions to serve as the final implementation. Hence the reason that all definitions must match.
And that's about it. The inline
keyword basically means that the function definition is in a header file. It tells the linker to not complain when that definition appears in multiple translation units, because that is expected.
Going back to the question, it looks like the intent was to declare an inline
function whose definition would appear in only one translation unit. In other words, the function would be flagged as defined in multiple translation units, but the definition would be in only one. Kind of inconsistent there, if not outright contradictory.
extern inline void f(int) {}
looks a bit strange. You've given a definition for a function that is marked as being defined elsewhere. – LaudianThe definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed.
The functioninline void f(int) {}
already has external linkage and must be defined inb.cpp
. The function already has external linkage.static inline void f(int){}
has internal. – Cloughextern inline void f(int);
will only allow you to take an address off
but not invokef()
directly. You still need to provide the definition in each translation unit for that. – Salableinline
) and telling him to go and look for it in another translation unit (extern
) – Crullerinline
function could be defined in more than one translation unit (that's what it means). Which one isextern
going to choose? – Crullerextern
andinline
at the same time? – Cruller