I'm trying to extern an inline function. How I thought it should work:
//a.cpp
inline void f(int) {}
//b.cpp
extern void f(int);
int main() { f(4); }
But getting link error. Then by reading this ("1) It must be declared inline
in every translation unit."). What I've tried:
//a.cpp
inline void f(int) {}
//b.cpp
extern inline void f(int);
int main() { f(4); }
Still getting link error. But now, trying something that I don't know what I'm doing:
//a.cpp
extern inline void f(int) {}
//b.cpp
extern inline void f(int);
int main() { f(4); }
It works. What's happening here? Before adding extern
to everything, f
in a.cpp
had internal linkage?
I'm using MSVC 2017 (v141) with /permissive-
and /std:c++17
Internal linkage refers to everything only in scope of a translation unit. External linkage refers to things that exist beyond a particular translation unit. In other words, accessible through the whole program, which is the combination of all translation units (or object files).
To use internal linkage we have to use which keyword? Explanation: static keyword is used for internal linkage.
The linker goes through the compiled code and finds x and z first. As they are global variables, they are externally linked by default.
The linker can inline small functions in place of a branch instruction to that function. For the linker to be able to do this, the function (without the return instruction) must fit in the four bytes of the branch instruction.
Nevertheless, in C++, inline functions are treated by default as having external linkage, meaning that the program behaves as if there is only one copy of the function. The function will have the same address in all translation units and each translation unit will share any static locals and string literals.
Internal Linkage: An identifier implementing internal linkage is not accessible outside the translation unit it is declared in. Any identifier within the unit can access an identifier having internal linkage.
Inline linking (also known as hotlinking, leeching, piggy-backing, direct linking, offsite image grabs) is the use of a linked object, often an image, on one site by a web page belonging to a second site. One site is said to have an inline link to the other site where the object is located.
There may be more than one definition of an inline function or variable (since C++17) in the program as long as each definition appears in a different translation unit and (for non-static inline functions and variables (since C++17)) all definitions are identical.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With