Randolf
Randolf

Reputation: 125

Inline functions in cpp files of shared libraries

From my understanding inline functions can go in headers as well as in the source files (with inline keyword) and by default memeber functions defined in headers are tried be inline by the compiler.

My question is with following source files, add.h

#ifndef ADD_H
#define ADD_H
class Add {
    public:
        int add(int a, int b);
};
#endif  /* ADD_H */

add.cpp

#include <iostream>
#include "add.h"

inline int Add::add(int a, int b) {
    std::cout << "FUNC: " << __func__ << std::endl;
    return a + b;
}

main.cpp

#include "add.h"

int main() {
    Add a;
    a.add(6,7);
    return 0;
}

If i compile the add.cpp and main.cpp

g++ -c add.cpp
g++ -c main.cpp
g++ main.o add.o

It complains about

main.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `Add::add(int, int)'
collect2: error: ld returned 1 exit status

looking at the symbols in add.o,

     U __cxa_atexit
                 U __dso_handle
000000000000003d t _GLOBAL__sub_I_add.cpp
0000000000000000 t __static_initialization_and_destruction_0(int, int)
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
0000000000000000 r std::piecewise_construct
0000000000000000 b std::__ioinit

It doesn't have add function in it which i assume is because the function is inline in .cpp. My question is when we have shared libraries, is it required to define functions inline in headers (add.h in the example) so that source files (main.cpp in the example) using the library gets the functions inlined at obj creation itself? It made no difference when using -flto at linking because function isn't present in the add.o?

Upvotes: 1

Views: 5490

Answers (2)

Pete Becker
Pete Becker

Reputation: 76523

If you define a function in a header file, every source file that #includes that header gets a copy of that function. You'll get a complaint from the linker that there are duplicate definitions.

If you define a function in a header file and mark it inline, every source file that #includes that header gets a copy of that function, but you've told the compiler that that's okay, and the linker won't complain.

If you define a function in a source file and don't mark it inline it's visible to code in other source files, so they can call that function.

If you define a function in a source file and mark it inline it's not visible to code in other source files. That's the problem here: Add is defined in add.cpp, and it's marked inline, so it isn't visible to main.cpp. You can either remove the inline or move the definition from add.cpp to add.h. If you move it to add.h you can keep it as is and put it after the class definition, or you write it directly inside the class definition and not mark it inline.

Linker optimization is completely separate from this. Formally, inline means "expand this function in line if you can", but compilers generally know better than you do what should be done. Linker optimization can expand functions inline, without regard to the inline keyword and without regard to visibility from other files. But the code has to be correct to begin with, so you have to resolve that missing symbol by fixing the code, not by trying to force some linker optimization.

Upvotes: 8

Adam Lamers
Adam Lamers

Reputation: 1243

You could put the function definition inside the header. It's implied to be inline if it's defined inside the class definition.

There's a good answer to this question here

Upvotes: 3

Related Questions