c++inline

Can I stop using "inline" altogether?


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


Solution

  • 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.