karlosss
karlosss

Reputation: 3155

Linking error on inline function declared in hpp, implemented in cpp and used in another cpp

I am getting linker errors undefined reference to function when I try to compile the following project:

header.hpp

inline void f(double*, double*, double*);

impl.cpp

inline void f(double* A, double* B, double* C){ ... }

use.cpp

#include "header.hpp"

int main(){
    double *A, *B, *C;
    f(A, B, C);
    return 0;
}

I compile with g++ -std=c++11 header.hpp impl.cpp use.cpp. Linker then says undefined reference to f in file use.cpp.

I noticed that if I remove the inline keyword, everything works fine, but I would like to keep it.

Also, I noticed that if in use.cpp I include impl.cpp instead, everything also works fine, but again, that is not what I want to do, as I want to produce multiple binaries using files impl.cpp, impl2.cpp and so on, and thus hardcoding one of those is also not the way.

Is there any way how to make such a project compile and link?

Upvotes: 1

Views: 416

Answers (2)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122565

The inline specifier is not to tell the compiler that it should inline this function while doing optimizations. This has been the case long time ago, but meanwhile it was realized that compilers are a lot better in making this decision:

The original intent of the inline keyword was to serve as an indicator to the optimizer that inline substitution of a function is preferred over function call, that is, instead of executing the function call CPU instruction to transfer control to the function body, a copy of the function body is executed without generating the call. This avoids overhead created by the function call (passing the arguments and retrieving the result) but it may result in a larger executable as the code for the function has to be repeated multiple times.

Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above.

You need inline when you want to define a function inline ;). In your example, inline would allow you to have

inline void f(double*, double*, double*) {}

in the header. The linker would not complain when it finds several definitions of that function (because the header can be included in several sources), because you declared it as inline.

the code is meant to be benchmarked and I wanted to prevent the overhead of calling a function

If removing the overhead of calling the function is a viable optimization, the compiler will realize that and act accordingly.

Upvotes: 5

sparik
sparik

Reputation: 1201

The definition of an inline function or variable (since C++17) must be reachable in the translation unit where it is accessed (not necessarily before the point of access).

source: https://en.cppreference.com/w/cpp/language/inline

use.cpp does not have access do the definition of f, that's why you get a linker error.

Why do you want f to be inline?

Upvotes: 0

Related Questions