Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defined multiple times for the inline function, how possible?

The following quote from c++ primer book confuse me a lot

Unlike other function, inline and constexpr functions may be defined multiple times in the program. After all, the compiler needs the definition, not just the declaration, in order to expand the code. However, all of the definitions of a given inline or constexpr must match exactly. As a result, inline and constexpr functions normally are defined in headers. -- C++ primer 5th Ed, 240 pp

"may be defined multiple times in the program" This quote confuse me a lot. As far as I understand, declaration can be made multiple time, but definition is only needed once.

can someone give me an example why there is a multiple definition.

like image 532
SLN Avatar asked Jan 27 '23 02:01

SLN


2 Answers

In a header file (lets call it foo.h) you can have

inline int foo() { /* do stuff */ }

Now if you include foo.h in a couple cpp files then foo will be defined in each of them, which would be a multiple definition error. Since foo is marked as inline though, it is okay because all of the definitions are the same.

As far as I understand, declaration can be made multiple time, but definition is only needed once

The compiler works on translation units (basically a cpp file) and in it, it can do all sorts of optimizations but function inlining and constexpr require that the compiler know the definition of the function. That means each translation unit needs the definition of the function in it. We use inline to make that okay, otherwise it would be a multiple definition error.

like image 59
NathanOliver Avatar answered Feb 16 '23 02:02

NathanOliver


As an example. This version isn't valid.

// main.cpp
inline int square(int num) {
    return num * num;
}

inline int square(int num) {
    return num * num;
}

int main()
{
    return square(2);
}

https://godbolt.org/z/nlSbxg

But when you have it in multiple .cpp files (aka. translation units) it is ok because it is now linker job to do right thing.

// b.cpp
inline int square(int num) {
    return num * num;
}

// main.cpp
inline int square(int num) {
    return num * num;
}

int main()
{
    return square(2);
}

Build: gcc main.cpp b.cpp Same way works #include it will place code in those .cpp files that's all.

Of course if body of function is inlined, then nothing to link so no problem :)

If compiler decides to do an out-of-line version you end up with more than one object file (.o) having definition for the same "inline" function. Such definition will be marked.

Thanks to that mark linker won't yield that it has found multiple definitions and just pick first one that it finds.

So if all definitions are truly the same, then fine! We will get into troubles if we have different body of such function. Example in file b.cpp

// b.cpp
inline int square(int num) {
    return 1;
}

It is undefined behavior to have multiple different definitions of the same inline function. It will compile of course but what we get? It depends on linker choice :D

like image 37
Dawid Avatar answered Feb 16 '23 03:02

Dawid