Since it's entirely up to compiler whether or not it inlines my functions can I just stop using this keyword completely (assuming it will inline everything it can anyway)?
You can stop using inline
as an optimization technique.
inline
is basically useful only when you want the ODR (One Definition Rule) not to apply. In short, you can mark functions as inline
and provide their definition directly in one header file, which is then imported by multiple translation units, without the linker complaining about this:
foo.hpp
inline int foo() { return 42; }
foo.cpp
#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline,
// because its definition is imported also in main.cpp
void bar()
{
int x = foo();
}
main.cpp
#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline,
// because its definition is imported also in foo.cpp
int main()
{
std::cout << foo();
}
The presence of the inline
keyword (which, again, does not guarantee that the compiler will perform inlining) ensures that the linker will merge those definitions.
Of course, in order for this merge operation to be meaningful, all the definitions of a function marked as inline
which end up being part of several different translation units must be identical. If this is not the case, your program has Undefined Behavior and no diagnostic is required - which means that your compiler/linker is not required to detect this inconsistency and tell you that something is wrong!
Per Paragraph 3.2/4 of the C++11 Standard, in fact:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.
Notice, that you can have the same function marked as inline
and literally defined twice in different translation units, and that is fine as long as those definitions are identical:
foo.cpp
inline int foo() // Has the same body in main.cpp, no problem!
{
return 42;
}
main.cpp
inline int foo() // Has the same body in foo.cpp, no problem!
{
return 42;
}
int main()
{
std::cout << foo();
}
However, if the two definitions differ, you will inject UB in your code, as in the following example:
foo.cpp
inline int foo()
{
return 42; // <== WATCH OUT! Different body in main.cpp
}
main.cpp
inline int foo()
{
return -42; // <== WATCH OUT! Different body in foo.cpp
}
int main()
{
std::cout << foo();
}
This is why you normally mark functions as inline
when you provide their definition directly in a commonly #include
d header file.
Also notice, that class member functions whose definition is directly inlined in the class definitions are automatically marked as inline
.