1

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?

Randolf
  • 125
  • 1
  • 9
  • 1
    No, no, no. If a function is inlined - it's inline. It doesn't matter if the function is defined in a .h header or a .cpp source file; it doesn't matter if it's a .dll/.so shared library or a .exe executable. One caveat: [Why am I getting LNK2019 unresolved external for my inline function?](https://blogs.msdn.microsoft.com/oldnewthing/20130509-00/?p=4413/) – paulsm4 Dec 10 '15 at 17:35
  • You have to use -flto at compile time too. Did you try that? – kchoose2 Dec 10 '15 at 17:43

2 Answers2

8

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • I think by "Linker optimization" you mean link-time optimization, it's performed by the compiler, not the linker. Also the "formal" definition you mentioned of `inline` is far from being formal. – Hadi Brais Dec 10 '15 at 18:23
3

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

Community
  • 1
  • 1
Adam Lamers
  • 1,183
  • 7
  • 8
  • which is what i am doing now, and that was my question, is that only way? – Randolf Dec 10 '15 at 17:33
  • 2
    Ah, my bad, I must have skimmed that part. In that case, here's a similar question with a good explanation: http://stackoverflow.com/questions/3992980/c-inline-member-function-in-cpp-file – Adam Lamers Dec 10 '15 at 17:35
  • thanks for the link,I thought so, then the second part of my question is with -flto link time optimization, could be an option? – Randolf Dec 10 '15 at 17:40
  • 1
    I believe lto can only inline normal functions it determines to be inline-able. As a secondary source, this quote from Wikipedia on inline functions seems to indicate that the function definition must be available to any compilation unit using a function declared as inline. "In C++, it is necessary to define an inline function in every module (compilation unit) that uses it, whereas an ordinary function must be defined in only a single module. Otherwise it would not be possible to compile a single module independently of all other modules." – Adam Lamers Dec 10 '15 at 17:48