Search code examples
c++inlinelinkage

What is the real nature of inline keyword in relation to linkages?


I have a serious problem to reconcile the "inline concept" with "linkage" with my humble knowledge:

  • I've heard we can use extern to access "a non-static entity" (like an entity that is NOT declared with static key) from other files
    = YES! I GOT THIS
  • They say we can use inline to make a function or variable appear in a "header file" and so that it can be accessed across multiple translation units
    = YES! I GOT THIS
  • They also say "an inline entity" can have either "internal or external linkage"
    = I DIDN'T GET IT

( A: Inline functions with internal linkage? - This where I first heard about an inline entity with "internal linkage" )

An inline entity can be accessed from anywhere across multiple translation units, so doesn't it mean that "an inline entity" should always have "external linkage" as granted?

What is the point of "an inline entity" which can be accessed from anywhere across multiple translation units and has "INTERNAL linkage"?

Any answer or any confirmation that I was wrong in any point would be appreciated.


Solution

  • The answer you've linked relates to C's inline, which works slightly differently. However, in either language, inline does not affect linkage.

    inline on a function makes it an inline function. By default, any free function has external linkage, which basically means that all functions f declared in multiple translation units refers to the same f. static would make make the functions have internal linkage, which means that every translation unit has its own f.

    // inline function with external linkage
    inline void f() { }
    
    // also an inline function with external linkage
    extern inline void g() { }
    
    // inline function with internal linkage
    static inline void h() { }
    
    namespace { // anonymous namespace
    // also an inline function with internal linkage
    inline void k() { }
    }
    

    An inline entity can be accessed from any where across multiple translation units, so doesn't it mean that "an inline entity" should always have "external linkage" as granted?

    A function doesn't have to be an inline function to be accessible in multiple TUs. inline just means that it can be defined in multiple TUs, not just declared, and this won't cause any linker errors (all definitions must be identical). In other words, the one-definition rule is relaxed for inline functions. And yes, as stated above, free functions have external linkage by default, even if they are inline.

    What is the point of "an inline entity" which can be accessed from anywhere across multiple translation units and has "INTERNAL linkage"?

    None. If it's accessible in multiple translation units, then it shouldn't have internal linkage. The benefit of internal linkage is that you can define it differently with the same name in different TUs. static inline in headers is an anti-pattern from C, which is motivated by the problem that unlike in C++, if a function isn't inlined, the linker will looks for an extern definition in some object file instead, which may not exist.

    // assuming all of the following are defined in a header ...
    
    // C: if f() isn't inlined, we get linker errors
    //    to solve this, declare an extern inline definition in some source file
    // C++: if f() isn't inlined, this is okay; the linker will pick one of N definitions,
    //      which are automatically generated in the non-inlined case
    inline void f() {}
    
    // C: if h() isn't inlined, duplicates get emitted into multiple TUs
    // C++: same, but this is stupid and avoidable; don't use 'static inline'
    static inline void h() {}