110

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?

6
  • 2
    Where does the snippet "and each instance of these functions have their own copies of static local variables & string literals" come from? Commented Jun 4, 2012 at 6: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. Commented Jun 4, 2012 at 6: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. Commented Jun 4, 2012 at 6: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. Commented Jun 4, 2012 at 6:18
  • 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. Commented Mar 20, 2013 at 2:31

5 Answers 5

81

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
Sign up to request clarification or add additional context in comments.

22 Comments

@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.
@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.
there is no notion of preference of an unnamed namespace over static. both have the same effect wrt linkage.
@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?
"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.
|
32

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.

1 Comment

"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.
23

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

5 Comments

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.").
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
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.
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.
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".
17

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
}

5 Comments

I do not understand your answer,Can you please elaborate in detail What is different and How it is different?
If disagree inline is useless. It is "only" a hint, but still, it is a hint, and compilers give some value to this hint.
"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, 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).
With /Ob1 inline is a hint the funcion can be inlined. Without being marked as inline the funcion is never inlined.
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.

4 Comments

... but also inlining the code everywhere it gets called and so increasing the size of the generated code by that bit. No?
@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.)
@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.
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.