Should one never use static inline function?

100,758

Solution 1

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

Solution 2

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.

Solution 3

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

Solution 4

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
}

Solution 5

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.

Share:
100,758

Related videos on Youtube

Alok Save
Author by

Alok Save

Alok is a long time C & C++ enthusiast.He wrote his first commercial C++ program more than a decade ago and has been in love with C++ ever since. He is known to dabble in Java,Pro-C,SQL,PLSQL,Unix scripting & many more languages.He has worked in various technical roles ranging from a programmer to a technical solutions architect.In his spare time he loves answering questions,especially on C & C++. -:Alok's LinkedIn:- SO Milestones: c++ Gold Badge (18/07/2011) c Gold Badge (02/01/2011) legendary Legendary Badge (29/05/2012) Some personal favorite answers:- Why I can't initialize non-const static member or static array in class? When to mark a function in C++ as a virtual? Previous definition error Destructor not invoked when an exception is thrown in the constructor Contribution to c++-faq :- What are Access specifiers? Should I inherit with private,protected or public? Why should one replace default new and delete operators? How should I write ISO C++ Standard conformant custom new and delete operators? What is this weird colon-member syntax in the constructor? What is the difference between char a[] = "string"; and "char *p = string;" External links he likes/recommends: C++ Faq Bjarne Stroustrup's C++ Style and Technique FAQ Bjarne Stroustrup's general faq C-Faq Clockwise Spiral Rule What Every Programmer Should Know About Floating-Point Arithmetic

Updated on May 13, 2020

Comments

  • Alok Save
    Alok Save about 4 years

    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?

    • Mars
      Mars almost 12 years
      Where does the snippet "and each instance of these functions have their own copies of static local variables & string literals" come from?
    • Nawaz
      Nawaz almost 12 years
      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.
    • Alok Save
      Alok Save almost 12 years
      @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
      Alok Save almost 12 years
      @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.
    • Abhijit-K
      Abhijit-K almost 12 years
      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?
    • Sam Kauffman
      Sam Kauffman about 11 years
      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.
  • Alok Save
    Alok Save almost 12 years
    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.
  • Mac
    Mac almost 12 years
    @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.
  • Potatoswatter
    Potatoswatter almost 12 years
    @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.
  • Alok Save
    Alok Save almost 12 years
    @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
    Alok Save almost 12 years
    I do not understand your answer,Can you please elaborate in detail What is different and How it is different?
  • Suma
    Suma almost 12 years
    If disagree inline is useless. It is "only" a hint, but still, it is a hint, and compilers give some value to this hint.
  • Potatoswatter
    Potatoswatter almost 12 years
    @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.
  • Suma
    Suma almost 12 years
    "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.
  • iammilind
    iammilind almost 12 years
    @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).
  • Suma
    Suma almost 12 years
    With /Ob1 inline is a hint the funcion can be inlined. Without being marked as inline the funcion is never inlined.
  • Alok Save
    Alok Save almost 12 years
    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?
  • Johannes Schaub - litb
    Johannes Schaub - litb almost 12 years
    there is no notion of preference of an unnamed namespace over static. both have the same effect wrt linkage.
  • Johannes Schaub - litb
    Johannes Schaub - litb almost 12 years
    @als "without breaking the odr" does not make sense because the odr does not disallow it.
  • Potatoswatter
    Potatoswatter almost 12 years
    @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?
  • Robert Calhoun
    Robert Calhoun over 10 years
    Interestingly your suggestion to use static inline as a replacement for macros is specifically recommended under this linux kernel style guide. ("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.").
  • M.M
    M.M almost 10 years
    "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.
  • Potatoswatter
    Potatoswatter almost 10 years
    @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.
  • Z boson
    Z boson over 8 years
    @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
    Z boson over 8 years
    @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?
  • Potatoswatter
    Potatoswatter over 8 years
    @Zboson You might be confusing static with inline. Please open a new question and provide an example.
  • Z boson
    Z boson over 8 years
    @Potatoswatter, no I don't think I am. I mean static functions in a header file.
  • Arvid
    Arvid almost 8 years
    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
  • Potatoswatter
    Potatoswatter about 7 years
    @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.)
  • Z boson
    Z boson about 7 years
    @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) agner.org/optimize/vectorclass.zip.
  • Z boson
    Z boson about 7 years
    "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.
  • Potatoswatter
    Potatoswatter about 7 years
    @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.
  • Leushenko
    Leushenko almost 7 years
    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.
  • Chris
    Chris almost 6 years
    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.
  • jww
    jww almost 5 years
    I believe you are not supposed to use anonymous namespaces in header-only implementations.
  • Potatoswatter
    Potatoswatter almost 5 years
    @jww And for the same reason never static functions either.
  • Eyal
    Eyal over 3 years
    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.
  • 0xC0000022L
    0xC0000022L over 2 years
    ... but also inlining the code everywhere it gets called and so increasing the size of the generated code by that bit. No?