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.
Q) Why is it not possible to inline function definitions in .cpp file?
You can inline functions in a cpp file.
What you can not do is access those inline functions from a different cpp file.
An inline function must be present in every file that uses it. That is why they often go in header files so any source needing to use it, includes the header containing it.
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.
From cppreference.com:
The definition of an inline function or variable (since C++17) must be
present in the translation unit where it is accessed (not necessarily
before the point of access).
Your functions are defined in test.cpp but you are accessing them from main.cpp.
Related
I'm getting a compiler error when I try to inline a method of one of my classes. It works when I take away the "inline" keyword.
Here's a simplified example:
main.cpp:
#include "my_class.h"
int main() {
MyClass c;
c.TestMethod();
return 0;
}
my_class.h:
class MyClass {
public:
void TestMethod();
};
my_class.cpp:
#include "my_class.h"
inline void MyClass::TestMethod() {
}
I try compiling with:
g++ main.cpp my_class.cpp
I get the error:
main.cpp:(.text+0xd): undefined reference to `MyClass::TestMethod()'
Everything is fine if I take away the "inline". What's causing this problem? (and how should I inline class methods? Is it possible?)
Thanks.
The body of an inline function needs to be in the header so that the compiler can actually substitute it wherever required. See this: How do you tell the compiler to make a member function inline?
7.1.2/4 of the Standard:
An inline function shall be defined in
every translation unit in which it is
used...
You use TestMethod in main.cpp, but it's not defined there.
... If a function with external linkage is
declared inline in one translation
unit, it shall be declared inline in
all translation units in which it
appears; no diagnostic is required.
You define (and hence also declare) TestMethod inline in my_class.cpp, but not in main.cpp.
The fix in this case is to move the function definition to the header file, either like this:
class MyClass {
public:
void TestMethod() {}
};
or like this:
class MyClass {
public:
inline void TestMethod();
};
inline void MyClass::TestMethod() {}
You've defined it as not inlined in the header file, while in the cpp file you're trying to define it as inline. That's a conflicted definition and it won't be able to find one from the other. Your header is where you really place the inline keyword.
However, I'd remove the inline keyword as it's really more of a suggestion to the compiler anyways. You really only need it when there's a free-floating function in the header and you don't want multiple definitions popping up in your code base.
NB This is not a question about how to use inline functions or how they work, more why they are done the way they are.
The declaration of a class member function does not need to define a function as inline, it is only the actual implementation of the function. For example, in the header file:
struct foo{
void bar(); // no need to define this as inline
}
So why does the inline implementation of a classes function have to be in the header file? Why can't I put the inline function the .cpp file? If I were to try to put the inline definition in the .cpp file I would get an error along the lines of:
error LNK2019: unresolved external symbol
"public: void __thiscall foo::bar(void)"
(?bar#foo##QAEXXZ) referenced in function _main
1>C:\Users\Me\Documents\Visual Studio 2012\Projects\inline\Debug\inline.exe
: fatal error LNK1120: 1 unresolved externals
The definition of an inline function doesn't have to be in a header file but, because of the one definition rule (ODR) for inline functions, an identical definition for the function must exist in every translation unit that uses it.
The easiest way to achieve this is by putting the definition in a header file.
If you want to put the definition of a function in a single source file then you shouldn't declare it inline. A function not declared inline does not mean that the compiler cannot inline the function.
Whether you should declare a function inline or not is usually a choice that you should make based on which version of the one definition rules it makes most sense for you to follow; adding inline and then being restricted by the subsequent constraints makes little sense.
There are two ways to look at it:
Inline functions are defined in the header because, in order to inline a function call, the compiler must be able to see the function body. For a naive compiler to do that, the function body must be in the same translation unit as the call. (A modern compiler can optimize across translation units, and so a function call may be inlined even though the function definition is in a separate translation unit, but these optimizations are expensive, aren't always enabled, and weren't always supported by the compiler)
functions defined in the header must be marked inline because otherwise, every translation unit which includes the header will contain a definition of the function, and the linker will complain about multiple definitions (a violation of the One Definition Rule). The inline keyword suppresses this, allowing multiple translation units to contain (identical) definitions.
The two explanations really boil down to the fact that the inline keyword doesn't exactly do what you'd expect.
A C++ compiler is free to apply the inlining optimization (replace a function call with the body of the called function, saving the call overhead) any time it likes, as long as it doesn't alter the observable behavior of the program.
The inline keyword makes it easier for the compiler to apply this optimization, by allowing the function definition to be visible in multiple translation units, but using the keyword doesn't mean the compiler has to inline the function, and not using the keyword doesn't forbid the compiler from inlining the function.
This is a limit of the C++ compiler. If you put the function in the header, all the cpp files where it can be inlined can see the "source" of your function and the inlining can be done by the compiler. Otherwhise the inlining would have to be done by the linker (each cpp file is compiled in an obj file separately). The problem is that it would be much more difficult to do it in the linker. A similar problem exists with "template" classes/functions. They need to be instantiated by the compiler, because the linker would have problem instantiating (creating a specialized version of) them. Some newer compiler/linker can do a "two pass" compilation/linking where the compiler does a first pass, then the linker does its work and call the compiler to resolve unresolved things (inline/templates...)
The c++ inline keyword is misleading, it doesn't mean "inline this function". If a function is defined as inline, it simply means that it can be defined multiple times as long as all definitions are equal. It's perfectly legal for a function marked inline to be a real function that is called instead of getting code inlined at the point where it's called.
Defining a function in a header file is needed for templates, since e.g. a templated class isn't really a class, it's a template for a class which you can make multiple variations of. In order for the compiler to be able to e.g. make a Foo<int>::bar() function when you use the Foo template to create a Foo class, the actual definition of Foo<T>::bar() must be visible.
The reason is that the compiler has to actually see the definition in order to be able to drop it in in place of the call.
Remember that C and C++ use a very simplistic compilation model, where the compiler always only sees one translation unit at a time. (This fails for export, which is the main reason only one vendor actually implemented it.)
I know this is an old thread but thought I should mention that the extern keyword. I've recently ran into this issue and solved as follows
Helper.h
namespace DX
{
extern inline void ThrowIfFailed(HRESULT hr);
}
Helper.cpp
namespace DX
{
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
std::stringstream ss;
ss << "#" << hr;
throw std::exception(ss.str().c_str());
}
}
}
Because the compiler needs to see them in order to inline them. And headers files are the "components" which are commonly included in other translation units.
#include "file.h"
// Ok, now me (the compiler) can see the definition of that inline function.
// So I'm able to replace calls for the actual implementation.
Inline Functions
In C++ a macro is nothing but inline function. SO now macros are under control of compiler.
Important : If we define a function inside class it will become Inline automatically
Code of Inline function is replaced at the place it is called, so it reduce the overhead of calling function.
In some cases Inlining of function can not work, Such as
If static variable used inside inline function.
If function is complicated.
If recursive call of function
If address of function taken implicitely or explicitely
Function defined outside class as below may become inline
inline int AddTwoVar(int x,int y); //This may not become inline
inline int AddTwoVar(int x,int y) { return x + y; } // This becomes inline
Function defined inside class also become inline
// Inline SpeedMeter functions
class SpeedMeter
{
int speed;
public:
int getSpeed() const { return speed; }
void setSpeed(int varSpeed) { speed = varSpeed; }
};
int main()
{
SpeedMeter objSM;
objSM.setSpeed(80);
int speedValue = A.getSpeed();
}
Here both getSpeed and setSpeed functions will become inline
I'm a C++ noob. I have a foo.cpp file which defines a function,
void sort() {
// details of sort algorithm
}
I have not defined this in the corresponding header file, but I get no compilation error. I noticed this is taken as a static method. Is that the case? What exactly have I done here?
EDIT:
I've noticed that inside this method I can't use this, (ex: this->bar), hence my assumption that this is a static function. This actually happened when I wanted a 'private' method, but forgot to declare it in the header file. Is there an actual use of such a function?
It is not invisible outside of that compilation unit, it is not bound to a single compilation unit, it is just a definition that needs a declaration in order to be called. Like any other definition.
wtf.cpp:
#include <iostream>
void f(){ std::cout<< "f();"; }
omg.cpp:
void f(); // I can declare wherever I use it.
int main(){ f(); }
$ g++ wtf.cpp omg.cpp && ./a.out
Output: f();
No, it is not taken as a static function. It is just not visible to the other transllation unnits, and so you cannot use it.
The difference in regard to a static method is, that the linker sees the function. So if you define a function with the same name in another translation unit, you will probably either get a linker error (best case) or the wrong method called at times.
PS: I talk about a functions rather than methods here, because in C++ a method typically is part of a class, and you cannot define a method for a class if that method isn't declared in that class' declaration.
the function is like the others said available in that translation unit.
But you can still access it from anywhere as it will just have external linkage. so just do this:
void foo()
{
extern void sort();
sort();
}
Nothing happens. The function will be there and essentially available, but without a prototype/forward declaration other translation units/parts of the code won't know it's actually there (and based on optimization level it might be excluded from the resulting executable code).
You've created a function that is only visible to that compilation unit (and others that include the source itself).
You've just have defined a free function .
You can use in your implementation file given that the declaration is above the calls (the parser "reads" the source file from top to bottom) :
void fun(){
mysort(); // Compile Error
void mysort(){}
void anotherFun(){
mysort(); // Works here
}
To get rid of this boundary effect, you can add a prototype of the function at the beginning of the file. I often use this "free function" for small conversion macros.
Example :
char* BigEndianToLitteEndian( char word[], int size); // prototype
void routine()
{
....
le = BigEndianToLittleEndian( be, SIZE );
....
}
char* BigEndianToLitteEndian( char word[], int size){ // implementation
....
}
Even though it's only in the implementation file, it's not static unless you specify static.
Static functions, in addition to restricting access, may also allow for compiler optimizations for better performance.
See static function in C, notably #Stephen_Canon's answer.
And also it might be very bad if the same function defined inside some other cpp file with the same signature.
I have three files:
1. Joy.h
class Joy
{
public:
void test();
};
2. Joy.cpp
#include "Joy.h"
inline void Joy::test() {}
3. main.cpp
#include "Joy.h"
int main()
{
Joy r;
r.test();
return 0;
}
I try to compile them using:
g++ cpp Joy.cpp
g++ say:
main.cpp:(.text+0x10): undefined reference to `Joy::test()'
Who can tell me why...
How to solve this problem if I don't want to define that test() function in the .h file and still want it to be an inline function?
when you define an inline member function, you should prepend the member function's definition with the keyword inline, and you put the definition into a header file.
When you declare a function inline basically You are telling the compiler to (if possible)replace the code for calling the function with the contents of the function wherever the function is called. The idea is that the function body is is probably small and calling the function is more overhead than the body of the function itself.
To be able to do this the compiler needs to see the definition while compiling the code which calls the function this essentially means that the definition has to reside in the header because the code which calls the function only has access to the header file.
Good Read:
[9.7] How do you tell the compiler to make a member function inline?
From the standard (N3242, 7.1.2.4):
An inline function shall be defined in every translation unit in which
it is used and shall have exactly the same definition in every case.
Have a look here as well: How do you tell the compiler to make a member function inline?
The compiler needs the complete definition of the function so that it could be inlined where it is called from. That is possible only if you define it in the header itself.
How does inline function work?
Say, you define this:
inline void increment(int &i) { ++i; }
and then use it as:
int i = 0;
while( i < N )
{
std::cout << i << std::endl;
increment(i);
}
then the compiler translates this code into this (roughly speaking):
int i = 0;
while( i < N )
{
std::cout << i << std::endl;
++i; //replaced the call with the equivalent code which the function
//actually executes to produce the same effect
//(edit typo) it replaces to ++i and not i++ as it was the original.
}
Such replacement of function-call with the code of function itself is said to be inlined. You can say, the function is inlined.
Note that the inline keyword is just a hint for the compiler : it tells the compiler if possible inline me. It is not guaranteed that every inline function call will be inlined by the compiler.
Because of the way C++ is compiled in to separate compilation unit (each cpp file typically), the compilation of one cpp file know not of the implmentation of the inlined function in another compilation unit so can't inline it.
The solution is to put the implementation of the inlined function in the header file this way all files using the head have access to the implementation,
an inline function is a function upon which the compiler has been requested to perform inline expansion.
Hence, the whole point of an inline function is that it is implemented in line. There isn't any way to define it in another source file if you still want it to be an inline function.
I'm getting a compiler error when I try to inline a method of one of my classes. It works when I take away the "inline" keyword.
Here's a simplified example:
main.cpp:
#include "my_class.h"
int main() {
MyClass c;
c.TestMethod();
return 0;
}
my_class.h:
class MyClass {
public:
void TestMethod();
};
my_class.cpp:
#include "my_class.h"
inline void MyClass::TestMethod() {
}
I try compiling with:
g++ main.cpp my_class.cpp
I get the error:
main.cpp:(.text+0xd): undefined reference to `MyClass::TestMethod()'
Everything is fine if I take away the "inline". What's causing this problem? (and how should I inline class methods? Is it possible?)
Thanks.
The body of an inline function needs to be in the header so that the compiler can actually substitute it wherever required. See this: How do you tell the compiler to make a member function inline?
7.1.2/4 of the Standard:
An inline function shall be defined in
every translation unit in which it is
used...
You use TestMethod in main.cpp, but it's not defined there.
... If a function with external linkage is
declared inline in one translation
unit, it shall be declared inline in
all translation units in which it
appears; no diagnostic is required.
You define (and hence also declare) TestMethod inline in my_class.cpp, but not in main.cpp.
The fix in this case is to move the function definition to the header file, either like this:
class MyClass {
public:
void TestMethod() {}
};
or like this:
class MyClass {
public:
inline void TestMethod();
};
inline void MyClass::TestMethod() {}
You've defined it as not inlined in the header file, while in the cpp file you're trying to define it as inline. That's a conflicted definition and it won't be able to find one from the other. Your header is where you really place the inline keyword.
However, I'd remove the inline keyword as it's really more of a suggestion to the compiler anyways. You really only need it when there's a free-floating function in the header and you don't want multiple definitions popping up in your code base.