102

There are two implications of using the inline keyword(§ 7.1.3/4):

  1. It hints the compiler that substitution of function body at the point of call is preferable over the usual function call mechanism.
  2. Even if the inline substitution is omitted, the other rules(especially w.r.t One Definition Rule) for inline are followed.

Usually any mainstream compiler will substitute function body at the point of call if needed, so marking function inline merely for #1 is not really needed.

Further w.r.t #2, As I understand when you declare a function as static inline function,

The static keyword on the function forces the inline function to have an internal linkage(inline functions have external linkage) Each instance of such a function is treated as a separate function(address of each function is different) and each instance of these functions have their own copies of static local variables & string literals(an inline function has only one copy of these)

Thus such a function acts like any other static function and the keyword inline has no importance anymore, it becomes redundant.

So, Practically marking a function static and inline both has no use at all. Either it should be static(not most preferred) or inline(most preferred),
So, Is using static and inline together on a function practically useless?

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 2
    Where does the snippet "and each instance of these functions have their own copies of static local variables & string literals" come from? – Jonas Byström Jun 04 '12 at 06:10
  • 3
    Is this what the Standard says >> *Usually any mainstream compiler will substitute function body at the point of call if needed, so marking function inline merely for #1 is not really needed.* – Nawaz Jun 04 '12 at 06:14
  • 2
    @JonasByström: **§ 7.1.3/4** *"If a function with ***external linkage*** is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. An inline function ***with external linkage*** shall have the same address in all translation units. A static local variable in an ***extern inline*** function always refers to the same object. A string literal in the body of ***an extern inline*** function is the same object in different translation units*". A function marked `static` has no external linkage, so inverse applies. – Alok Save Jun 04 '12 at 06:15
  • 1
    @Nawaz: No that is not what standard says(*I nowhere claimed it does*), I am saying that and it is based on behavior of most of the mainstream compilers.Usually the standard does not say anything about *implementations* it only talks about *observable behaviors* This Q is about practicality. – Alok Save Jun 04 '12 at 06:18
  • Still not getting this >>"and each instance of these functions have their own copies of static local variables & string literals". Someone help me understand. If somehow we have functions having copies of static variable and these functions also modify them (static variable) then how can the value of static variable be in sink? – Abhijit-K Jun 04 '12 at 06:43
  • 3
    Thought I'd add for clarity that this question is about `static` `inline` functions that are not class methods. For `static` `inline` _methods_, look [here](http://stackoverflow.com/questions/2133630/can-a-class-method-be-both-inline-and-static). – Sam Kauffman Mar 20 '13 at 02:31

5 Answers5

74

Your analysis is correct, but doesn't necessarily imply uselessness. Even if most compilers do automatically inline functions (reason #1), it's best to declare inline just to describe intent.

Disregarding interaction with inline, static functions should be used sparingly. The static modifier at namespace scope was formerly deprecated in favor of unnamed namespaces (C++03 §D.2). For some obscure reason that I can't recall it was removed from deprecation in C++11 but you should seldom need it.

So, Practically marking a function static and inline both has no use at all. Either it should be static(not most preferred) or inline(most preferred),

There's no notion of preference. static implies that different functions with the same signature may exist in different .cpp files (translation units). inline without static means that it's OK for different translation units to define the same function with identical definitions.

What is preferred is to use an unnamed namespace instead of static:

namespace {
    inline void better(); // give the function a unique name
}

static inline void worse(); // kludge the linker to allowing duplicates
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • But usually, One would add `inline` on the *definition*(cpp file) & not the *declaration*(header) of the function, So How does it help in being descriptive to users of my code? It might be useful to one who can see the source files only. – Alok Save Jun 04 '12 at 06:24
  • 3
    @Als: regardless of where it appears, it is more useful to *maintainers* of code, in order to declare intended or assumed behaviour of the code. It's not so useful for *users* of the code - whether the function's inline or not shouldn't (ideally) matter to them. – Mac Jun 04 '12 at 06:25
  • @Als A `static` function is usually not declared in the header file, so the declaration is optional and there's little difference anyway. An `inline` function must be declared and defined in the same file, so the same again applies. Also, that sounds like a really bad idea. If you want to choose one or the other, mark the declaration inline. Of course it's better to mark both. – Potatoswatter Jun 04 '12 at 06:27
  • @Potatoswatter: I am all for marking functions `inline` over `static` or anonymous namespace.`inline` is the most correct way to have a function definition in the header file.My Q is just about `static inline` being practically useless apart from as you said just perhaps being vocal of the intent. – Alok Save Jun 04 '12 at 06:29
  • 1
    @Als: `static` and `namespace{}` do (roughly) the same thing. `inline` does something else. Don't underestimate the value of describing intent. If you must have effects, an `inline` declaration is likely to make the compiler more aggressive about inlining. From what you've said so far, it sounds like you might have been misusing these specifiers for functions with declarations in a `.h` and definitions in a `.cpp`, which is wrong. – Potatoswatter Jun 04 '12 at 06:34
  • Thanks, I understand but Perhaps: *"static implies that multiple functions with the same name may exist with different definitions **without breaking the ODR**"* is better? – Alok Save Jun 04 '12 at 07:03
  • 3
    there is no notion of preference of an unnamed namespace over static. both have the same effect wrt linkage. – Johannes Schaub - litb Jun 04 '12 at 08:30
  • @als "without breaking the odr" does not make sense because the odr does not disallow it. – Johannes Schaub - litb Jun 04 '12 at 08:31
  • 3
    @JohannesSchaub-litb Well they're not necessarily exactly the same. They achieve the same thing wrt visibility between TUs within C++, but ABI/binary format effects may differ. `static` isn't guaranteed to generate a visible, unique name like `namespace{}` is. What was the reason for the un-deprecation? Was it ADL name association, the need to have the feature for language linkage, or something else? If ADL, isn't that fixed by `inline` namespaces? – Potatoswatter Jun 06 '12 at 06:56
  • 1
    "What is preferred is to use an unnamed namespace instead of static:" - preferred by whom, and why? Neither version should generate a name visible outside the TU. – M.M Jul 11 '14 at 00:49
  • @MattMcNabb Preferred by the committee that deprecated that usage of `static` back in 1998, and anyone who agrees with the comments in my example. I've yet to see an argument in favor of `static`. – Potatoswatter Jul 11 '14 at 01:10
  • @AlokSave, why do you say " I am all for marking functions inline over static or anonymous namespace"? The compiler can optimize static functions further. On the other hand static functions may make the code longer. Doesn't it depend on what your goal is? In may case I am almost always after efficiency otherwise I would use another language than C++. – Z boson Dec 07 '15 at 19:33
  • @Potatoswatter, you write "A static function is usually not declared in the header file". What's wrong with putting static functions in the header file? – Z boson Dec 07 '15 at 19:35
  • @Zboson You might be confusing `static` with `inline`. Please open a new question and provide an example. – Potatoswatter Dec 09 '15 at 10:01
  • @Potatoswatter, no I don't think I am. I mean static functions in a header file. – Z boson Dec 09 '15 at 14:23
  • @Zboson A `static` function declared in a header file must also be defined there, so it will be compiled and linked separately for each TU. Especially if it's too big to be `inline`, it may bloat the executable size and build time. (Sorry for the late reply.) – Potatoswatter Apr 28 '17 at 05:13
  • @Potatoswatter, I am aware of that. That's often what I want (each TU to optimize the static function as best it can and inline the code). Agner Fog built his VectorClass library as essentially several header files using `static inline` for each function (though `static` would be sufficient) http://www.agner.org/optimize/vectorclass.zip. – Z boson Apr 28 '17 at 06:46
  • @Zboson Again, there seems to be some confusion here between the effects of `static` and `inline`. In a C header library, adding `static` to `inline` may help by eliminating the need for an additional non-`inline` definition. But C++ doesn't have such a need, and using different functions in different TUs (per `static`) as if they were the same function, multiply defined (the usual behavior of `inline`) often violates the ODR. That library likely contains undiagnosed ODR violations, and usage of it certainly does. – Potatoswatter May 10 '17 at 01:18
  • I have to -1 this because there's no justification at all given for why adding `inline` tells a maintainer anything. `inline` has **no effect** on the optimization behaviour of any remotely recent compiler, and it's essentially none of the author's business how the code is generated or arguably whether such concepts even still apply to the heavily-rewritten output. It's not obvious how inlining has anything at all to do with maintenance because it's not obvious how it's in any way relevant to the code's "intent" in the first place. – Alex Celeste May 25 '17 at 16:27
  • How about structs being first class citizens within functions, and declaring local structs allows for local functors which avoid all the binding, lambdas, etc. `static` is the only thing which allows for this approach. – Chris Aug 07 '18 at 14:50
  • I believe you are not supposed to use anonymous namespaces in header-only implementations. – jww Jul 23 '19 at 04:04
  • @jww And for the same reason never `static` functions either. – Potatoswatter Jul 23 '19 at 04:12
30

Static and inline are orthogonal (independent). Static means the function should not be visible outside of the translation unit, inline is a hint to the compiler the programmer would like to have this function inlined. Those two are not related.

Using static inline makes sense when the inlined function is not used outside of the translation unit. By using it you can prevent a situation of accidental violation of ODR rule by naming another inlined function in another tranlation unit with the same name.

Example:

source1.cpp:

inline int Foo()
{
  return 1;
}

int Bar1()
{
  return Foo();
}

source2.cpp:

inline int Foo()
{
  return 2;
}

int Bar2()
{
  return Foo();
}

Without using static on Foo (or without using an anonymous namespace, which is preferred way by most C++ programmers), this example violates ODR and the results are undefined. You can test with Visual Studio the result of Bar1/Bar2 will depend on compiler settings - in Debug configuration both Bar1 and Bar2 will return the same value (inlining not used, one implementation selected randomly by the linker), in Release configuration each of them will return the intended value.

Suma
  • 33,181
  • 16
  • 123
  • 191
  • 3
    "Using `static inline` makes sense when the inlined function is not used outside of the translation unit." `static` makes sense, adding `inline` to it is pointless. – Z boson Apr 28 '17 at 06:48
21

I may not be completely right about this, but as far as I know declaring a function static inline is the only way to make (or allow) the compiler to generate a machine code where the function really is not defined in the compiled code at all, and all you have is a direct substitution of the function call into a sequence of instructions, like it were just a regular procedure body, with no trace in the machine code of a procedure call relative to that function definition from the source code.

That is, only with static inline you can really substitute the use of a macro, inline by itself is not enough.

A simple Google search for "static inline" will show you compiler documentation pages that talk about it. I guess this should be enough to answer your question, and say, "no, it is not practically useless". Here is one example of a site discussing the use of inline, and specifically of static inline http://www.greenend.org.uk/rjk/tech/inline.html

dividebyzero
  • 2,190
  • 1
  • 21
  • 33
  • 4
    Interestingly your suggestion to use `static inline` as a replacement for macros is specifically recommended under this [linux kernel style guide](https://www.kernel.org/doc/Documentation/SubmittingPatches). ("Static inline functions are greatly preferred over macros. They provide type safety, have no length limitations, no formatting limitations, and under gcc they are as cheap as macros."). – Robert Calhoun Aug 28 '13 at 13:52
  • 4
    the inline keyword in C has different semantics than C++. It's more complicated to have inline functions with external linkage in C, because the you have to manually pick the translation unit/object file where the non-inlined version is put. I believe the recommendation of using static inline is C-centric, and mostly motivated by convenience. Presumably it increases the risk of code duplication in the binary – Arvid May 24 '16 at 19:26
  • 1
    If you want to replace a macro, `extern inline` is a better fit. The difference is that `static inline` makes a version that isn't inline and the compiler can choose to use either. With `extern inline`, the non-inline version won't even exist. – Eyal Dec 28 '20 at 19:33
  • `static inline` seems pretty useless to me in a header file. If the `inline` is ignored by the compiler you get a different but identical binary definition created in each translated object, and the final binary will also have these duplicates that take up space without providing any performance benefit. I think the better use for `static inline` is when you want to define some small 'helper' subroutines in the .cpp file. I use them mostly for generating error messages or throwing custom exceptions so as not to clutter up the body my routines with tedious error handling boilerplate. – MarshallBS Nov 26 '22 at 20:55
  • If you don't put `inline` on inline functions in header file, the compiler will warn about unused static function for whichever translation unit that includes it. Thus, in this case `inline` is a way to tell the compiler "Yes, I know it's static, but it's going to be used as inline function". – syockit Mar 14 '23 at 04:44
16

If you talk about free functions (namespace scope), then your assumption is correct. static inline functions indeed don't have much value. So static inline is simply a static function, which automatically satisfies ODR and inline is redundant for ODR purpose.

However when we talk about member methods (class scope), the static inline function does have the value.
Once you declare a class method as inline, it's full body has to be visible to all translation units which includes that class.

Remember that static keyword has a different meaning when it comes for a class.
Edit: As you may know that static function inside a class doesn't have internal linkage, in other words a class cannot have different copies of its static method depending on the translation (.cpp) units.
But a free static function at namespace/global scope does have different copies per every translation unit.

e.g.

// file.h
static void foo () {}
struct A {
  static void foo () {}
};

// file1.cpp
#include"file.h"
void x1 ()
{
  foo();  // different function exclusive to file1.cpp
  A::foo();  // same function
}

// file2.cpp
#include"file.h"
void x2 ()
{
  foo();  // different function exclusive to file2.cpp
  A::foo();  // same function
}
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • I do not understand your answer,Can you please elaborate in detail *What* is different and *How* it is different? – Alok Save Jun 04 '12 at 06:30
  • 1
    If disagree inline is useless. It is "only" a hint, but still, it is a hint, and compilers give some value to this hint. – Suma Jun 04 '12 at 06:31
  • "compiler mostly ignores that hint" This depends on the compiler and the setting used. When you use a Visual Studio with /Ob1, the compiler complies to the hint. – Suma Jun 04 '12 at 06:43
  • 2
    @Suma, do you mean that, if you hint `inline` then MSVS inlines a recursive function call also (#1 effect in OP) with `/Ob1`? It's impossible. There can be other such cases where the function will not be replaced by its definition (e.g. function body is too big and is invoked at various places). There is no value of a hint. The only guaranteed effect of `inline` is #2 (from OP). – iammilind Jun 04 '12 at 06:53
  • 2
    With /Ob1 inline is a hint the funcion can be inlined. Without being marked as inline the funcion is never inlined. – Suma Jun 04 '12 at 06:54
3

I just read a man page for gcc and it specifically states the use of static inline with a compiler flag. In the case of the flag, it inlines the function and if it is also static and is inlined in every instance that it is called, then it gets rid of the function definition which will never be used in the created object file, thereby reducing the size of the generated code by that little bit.

Luke Small
  • 31
  • 1
  • 2
    ... but also inlining the code everywhere it gets called and so increasing the size of the generated code by _that_ bit. No? – 0xC0000022L Dec 14 '21 at 17:14
  • @0xC0000022L: Assuming your function was small enough that you wanted it inlined everywhere it's used, it would just be a waste of space for a non-inline definition to also exist in your final linked executable, with no callers. (Sometimes functions can be *very* simple after inlining, and optimize to fewer instructions that it would take to set up args and `call`, e.g. like for `std::vector::operator[]` especially in a loop where compiler is already keeping the pointer in a register. So it's not always true that inlining will increase overall code size for modern C++ with small templates.) – Peter Cordes May 14 '23 at 03:56
  • @PeterCordes I'm aware. I just felt the answer fell short on mentioning this as a potential downside. _Whether it is_ a downside is a judgment call and dependent on context. Also, small enough functions about which the compiler can "reason" on its own will often end up being inlined anyway, without special compiler switches. And last but not least we were talking about `static inline` which is of course _related_ to other forms of inlining, but not applicable in the example case you gave. But of course you are right that a method like that emits more opcodes when it has to be `call`-ed. – 0xC0000022L May 15 '23 at 12:16
  • In your given case it's pretty clear that the inlined method will likely not just be smaller but also faster (and overall code around it will have a higher chance of getting optimized better), but we should also not fall into the trap of assuming that more opcodes mean slower code. The wisdom of x86 assembler geeks of the 1990s, for example, is not really worth much these days. – 0xC0000022L May 15 '23 at 12:18