Search code examples
c++linkerinlineinline-functions

Why is it not possible to inline function definitions in .cpp file?


Why it is not possible to inline function or class member function definitions in .cpp files? For instance in my test examples below, the linker will give me back an undefined reference error if I try to inline a function or class member definition in the cpp file:

test.h

void print();

class A
{
    public:
        void print() const;
};

test.cpp

#include <test.h>

inline void print()
{
    // implementation
}

inline void A::print() const
{
    // implementation
}

main.cpp

#include <test.h>

int main(int argc, char** argv)
{
    print(); // undefined reference to `print()'
    A a;
    a.print(); // undefined reference to `A::print() const'

    return 0;
}

I have read some answers here, yet I am still uncertain how it works.


Solution

  • The inline keyword is really confusing, although, for this use-case it is still clear if you know the meaning.

    inline influences the requirements of the code that needs to be generated. More specifically, it tells to your compiler that it should not foresee a function pointer for that function. As always, it is allowed to copy the content into the caller. Because of inline, the original function does not have to be created. So you don't have a function pointer into test.o.

    In main.o, you call this function. Therefor, it tries to resolve the function pointer which was not created, which causes this linker error.

    Finding these cases can be done with for example a compiler warning by clang: -Wundefined-inline

    EDIT

    Will an inline function not have a function pointer? No, you can perfectly take the address of this function and use it and pass it. Although, because of the inline character of the function, you cannot rely on this function pointer comparing equal in comparison with another address of the same function.

    In this case, you will have somewhere the function pointer in your object file. However, in this case, the compiler doesn't require to give this the correct mangled name so it can be used from another compilation unit.