Inspired by the article "Why const
Doesn't Make C Code Faster", I want to carry out a similar experiment in my code base, but for inline
.
I have a feeling that a lot of code currently marked as inline
does not help. A few programmers I know still perceive it as an optimization hint to the compiler.
At the same time, trying to inline stuff means it often has to be placed in headers, which negatively affects the design in many aspects (unit testing, incremental build etc.) because everything has to know about everything, rather than being separated by interfaces and being independently deployable.
I want to produce a version of the source code that has as few inline
keywords as possible left in it, then benchmark it and compare against the baseline measurements done on the unmodified code base.
I wonder which of the following transformations that remove inline
preserve semantics of a well formed program, and thus can be carried out automatically (i.e., by find-and-replace).
static inline
with static
in a .cpp file (i.e., not in a header).static inline
with static
in a header. Assume that header has #pragma once
or include guards, so that it is guaranteed to be included only once.inline
without preceding static
with empty string. I do not believe this construct is used in my code base, but still it is of interest.The inline
keyword is used in several different contexts: for freestanding functions, for methods of a class, and even for data variables of class, so I'd expect that there will be some variation in what of those can be safely omitted and which are required.
If someone has already done this experiment, I welcome references to reports about how it went.
The other answers focus on the aspect of performance. I will try to answer your specific question. How does removing inline
specifier affect the semantics and correctness of a program?
In the following cases you can remove the inline
keyword and it will result in no semantic difference:
A function defined entirely inside a class/struct/union definition, whether it's a member function or a non-member friend function, is implicitly an inline function.
// header or cpp file
struct S
{
// no difference with or without the inline specifier
inline void foo() {}
};
A function declared inside an unnamed namespace (header or cpp file) has internal linkage. This effectively means that identical declaration/definition from different TU refer to different objects. This means there can't be any ODR violations.
// header or cpp file
namespace {
// no difference with or without the inline specifier
inline void foo() {}
}
A function declared with static
has internal linkage (see above)
// header or cpp
// no difference with or without the inline specifier
static inline void foo() {}
A function declared constexpr
on its first declaration is implicitly an inline function.
// header or cpp
// no difference with or without the inline specifier
constexpr inline void foo() {}
inline from (non-specialized) template functions can also be removed safely (thanks Jarod42)
// header or cpp
// no difference with or without the inline specifier
template <class T>
inline void foo(T) {}
In the following cases removing the inline specifier will cause an ODR violation NDR if the declaration/definition is used in multiple TUs
a function with external linkage used in more than one TU:
// header included in multiple TUs
// removing the inline specifier will cause ODR violations
inline void foo() {}
or
// a.cpp
// removing the inline specifier will cause ODR violations
inline void foo() {}
// b.cpp
// removing the inline specifier will cause ODR violations
inline void foo() {}
Technically if a non inline function with external linkage is used in one and only one TU the program is correct. However as soon as that function appears in a second TU the program will break without any warnings (NDR) due to the ODR violation.
Some quotes from https://en.cppreference.com/w/cpp/language/inline