9

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)?

NPS
  • 6,003
  • 11
  • 53
  • 90

2 Answers2

12

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 #included header file.

Also notice, that class member functions whose definition is directly inlined in the class definitions are automatically marked as inline.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • And, even if you never use `inline`, you can still use it implicitly: `struct Foo{ int x; Foo():x(0) {} };` in one .cpp file, and `struct Foo{ double d; Foo():d(0) {} };` in another .cpp file, and you just implicitly created two `inline` constructors called `Foo::Foo`... – Yakk - Adam Nevraumont Apr 07 '13 at 13:03
  • 1
    @Yakk: Then your program has undefined behavior, unless both `Foo` are declared in an anonymous namespace. – Matthieu M. Apr 07 '13 at 13:31
  • @MatthieuM. yep, and I've seen that happen in production code. Basically, I'm saying that even if you don't use `inline`, you can be bitten by it, so you need to understand what `inline` really is even if you don't use it. – Yakk - Adam Nevraumont Apr 07 '13 at 13:47
5

Depends on purpose of using inline.

The common (mis)conception:
inline is just a suggestion which a compiler may or may not abide to. A good compiler will anyways do what needs to be done.

While, the truth:

inline usually indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules(especially w.r.t One Definition Rule) for inline are followed.

So If your purpose of usage is optimizations the answer is:

YES, You can stop using inline. Most of modern day compilers will do that for you quite nicely.

But if your purpose of usage of inline is to allow you to get past the one definition rule and define a function body in a header file without breaking the ODR then answer is:

NO, You need to explicitly mark the functions as inline to be able to bypass the ODR.

Note: Member functions defined within the class body are implicitly inline, but same does not apply for free functions.

Alok Save
  • 202,538
  • 53
  • 430
  • 533