简体   繁体   中英

Does inline determine internal linkage?

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

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 (ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM