I already asked a similar question but this one is a bit different
I don't want to write a .cpp file for every simple c++ class.
when I write a class definition and declaration in a single .hpp file, the linker complains about multiple definition of member functions which are not implemented inside the body of the class or defined with inline keyboard.
For example this will work but member functions will become inline :
// log.hpp file
#pragma once
#include<iostream>
class log {
private:
static int m_cnt = 0;
public:
void log();
};
inline void log::log() {
std::cout << ++m_cnt << std::endl;
}
So I use templates to get rid of linker complaints and hope that member functions will not become inline(do they ?):
// log.hpp file
#pragma once
#include<iostream>
template<typename T>
class log_t {
private:
static int m_cnt = 0;
public:
void log();
};
template<typename T>
void log_t<T>::log() {
std::cout << ++m_cnt << std::endl;
}
// some random type (int)
typedef log_t<int> log;
And then I can simply use log class in multiple .cpp files without linker complaints.
even when i use this method will member functions become inline ?
While it is in general bad practice to put everything in a single .h file, there are situations where it's more convenient to do so. Especially when defining small classes, and during prototyping phase where the code can change a lot quickly.
I really don't recommend using templates to solve the linking issue, since it's can slow down compilation and leads to confusion: it's like creating a function taking an argument when you except that argument to always have the same value. Anyway, typing inline is shorter than template<typename T> ;)
So you either have to define your methods in the class body or annotate them with inline if defined out of the body. This is equivalent, since C++ automatically adds inline to methods defined in the class body.
Your concern appears to be with the generated code, you probably wonder if the binary is going to grow too much. But everything's cool since regardless of inline annotations, the compiler looks at every function call and decides whether to inline it or generate a call. This means the same function may sometimes be inlined (if called in a loop) and sometimes be called.
Different compilers have different heuristics, but the inline keyword doesn't have a particularly strong influence on the compiler's decision. You can use things like __forceinline or __attribute__((always_inline)) to make ask more strongly to inline a function, but even then there's no guarantee all calls to the function will be inlined. On the contrary, you may be interested in __attribute__(noinline) for gcc which will (nearly) never inline the call:
inline __attribute__(noinline) void log::log() // gcc
{
std::cout << ++m_cnt << std::endl;
}
If you want to really know what's happening in your code you can use -Winline to see when inline functions are not inlined.
You can also use -Os or -Oz optimization levels to change internal compiler thresholds, so that it will do less inlining.
Related questions which may interest you : here and here.
In general, having every implementation in header files is a BAD idea, since it can lead to very long compile times for larger projects. Using templates to avoid this is not really a good idea, either, since it does not change this fact.
inline is only a hint to the compiler; it may ignore it and inline your template code or not. In short: The answer to your question does not matter. The standard/best way would be to use .cpp files for the implementation, even if you want to avoid it.
Related
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
//header.h
#include<iostream>
using namespace std;
struct Base {
virtual void vf();
};
struct Derived :Base {
virtual void vf();
};
inline void Base::vf() {
cout << "Base::vf()" << endl;
}
inline void Derived::vf() {
cout << "Derived::vf()" << endl;
}
//source.cpp
#include"header.h"
int main() {
Base *pb = new Derived;
pb->vf();
}
//source2.cpp
#include"header.h"
It compiles and works in MSVC and g++.
But if I remove both inline keywords, a duplicate definition error will be caught by the linker since I include function definition twice, which will break the ODR.
Since I call the virtual function with a base pointer, it should be decided at run-time, and the compiler will ignore my inlining request, causing the duplicate error.
Do I get something wrong?
As the code is currently written, the member functions are defined in header.h and marked inline. That's okay from the perspective of the language definition: inline means "it's okay to have multiple [identical] definitions of this function". From a maintenance perspective it can make things harder. In particular, when you do this, every time you change the implementation of any of those functions you have to recompile all of the source files that use that header. Putting the definitions of those functions into their own source file[s] means you only have to recompile the file[s] that changed.
If you don't want to mark your functions inline (and you don't want to define them inside the class definition, which makes them implicitly inline), then you have to put each function definition into exactly one source file. A useful first step is to define all of the non-inline member functions of a class in a single source file. So your source2.cpp might look like this (yes, that's member functions from two classes):
#include "header.h"
#include <iostream>
void Base::vf() {
std::cout << "Base::vf()\n";
}
void Derived::vf() {
std::cout << "Derived::vf()\n";
}
and you'd remove those definitions from header.h. So now header.h contains only the class definition; source2.cpp has the definitions of the member functions; and source.cpp has the main function.
The One Definition Rule is mandatory. It is required by C++. A given object or a function must be defined exactly once. Removing the inline keyword (in your case) violates this rule, making the resulting program ill-formed.
Runtime polymorphism and virtual function dispatch happens at run time. You can only get to the run time part if your program is well-formed. If it breaks the ODR it is not well-formed, so how runtime polymorphism and virtual function dispatch works becomes a moot point. If your program is ill-formed there won't be anything to run and no base pointer at all.
It is true that an ODR violation does not require a diagnostic, but the resulting code is still broken. Please write a thank-you note to your compiler for alerting you to the problem.
First look at these templates.
struct INIWindows{
inline int GetInteger(){
return 100;
}
};
struct INILinux{
inline int GetInteger(){
return 120;
}
};
template <class Reader>
class SettingsManager : public Reader{
};
Edit: Addendum because it was not clear what i was doing.
int main(){
SettingsManager<INIWindows> Settings;
printf("Integer Reads %i\n",Settings.GetInteger());
system("pause");
return 0;
}
Is my understanding correct that this will result in SettingsManager having an inline function called get integer that will then be inlined properly by the compiler?
Is my understanding correct that this will result in SettingsManager having an inline function called get integer that will then be inlined properly by the compiler.
Yes, your understanding is correct. Your methods are going to be placed in the SettingsManager class, without a virtual dispatch, because the base classes (INIWindows and INILinux) do not have virtual methods.
The inline keyword is only a command for the compiler to try to inline the method - nothing else. It is free not to do it.
inline makes no sense inside a class. If you had defined the functions outside a class then it would indicate internal linkage. But in your current code does not serve any purpose whatsoever: all functions defined in a class are inline.
For the compiler, inline simply means that the name is no visible outside the compilation unit. In this regard, it’s similar to global static. Other than that, the compiler is free to perform function call inlining any way it wants.
In particular, the optimiser may choose to replace a call by the contents of a function. This is what you want, but it’s (almost completely) unrelated to the inline keyword, despite its name.
(By the way, this is unrelated to templates and template metaprogramming.)
In order to improve code readability, sometimes I use "alias methods". These are basically methods that all do the same thing (at least in the base class; derived classes may do it differently) with different names, that enhance code readability for the class user depending on the context. Consider the code below for an example:
template <typename T>
class Foo {
public:
T bar() { /* Lots of stuff here */ }
inline T bar_alias1() { return this->bar(); }
inline T bar_alias2() { return this->bar(); }
};
Of course, if Foo::bar() was a small function, one would simply duplicate the code in all the alias methods. However, since the code may be relatively large, code duplication should be avoided, hence why the alias methods are declared as inline. But I know that the compiler does not guarantee that any function declared as inline would actually end up being expanded at compile time.
So my question is, am I introducing any performance overhead by creating these alias methods? In the code below:
Foo<BIG_OBJECT> foo;
BIG_OBJECT bo1 = foo.bar();
BIG_OBJECT bo2 = foo.bar_alias1();
Would calling foo.bar() be faster than calling foo.bar_alias1() assuming the object being passed is relatively large? Are there redundant copies of the object being made when Foo::bar_alias1() calls Foo::bar()?
I'm using Visual Studio 2010 as my compiler.
Assuming the aliased functions are inlined - and they should given the size.
There shouldn't be any performance overhead. The code-size won't increase either if the compiler decides to omit the function code and inline all calls to it.
(I'm referring to the inlining of bar_alias1(), bar() itself won't necessarily be inlined if it's large.)
However, this doesn't apply if the functions are virtual.
In C, I would do this more directly with preprocessor, but I'm not sure how appropriate that is in C++.
Suppose the following template class is heavily used in a project with mostly int as typename and linker speed is noticeably slower since the introduction of this class.
template <typename T>
class MyClass
{
void Print()
{
std::cout << m_tValue << std::endl;;
}
T m_tValue;
}
Will defining a class specialization benefit compilation speed?
eg.
template <>
class MyClass<int>
{
void Print()
{
std::cout << m_tValue << std::endl;;
}
int m_tValue;
}
Or does explicit instantiation offers a better solution?
eg.
template class MyClass<int>;
in C++0x you will be able to use extern templates so that instantiation of templates happens only once just like extern variables.
This should help in compile times since the compiler would not have to instantiate the template with its arguments every time it sees it.
I haven't yet figured out exactly how I will be using this feature in my own projects, but anything that can help compile times is a plus for me.
http://www2.research.att.com/~bs/C++0xFAQ.html#extern-templates
By making the program more complex - longer, and requiring more disambiguation at a call-site - in general, a compiler will become slower not faster.
However, it's not likely to be a big issue unless you're automatically generating huge numbers of such specializations. Also, performance varies between compilers - you can always test it yourself (I expect the difference to be too small to be apparent without rigorous tests and a large number of test runs).
It's possible linker speed is reduced since the template is being declared "inline" (though not necessarily inlined) in all compilation modules in which it's referenced. When that occurs, you're duplicating a method all over the place and the linker gets more work. By comparison, a "normal" function with just a declaration in a header and the definition in just one spot will result in just one compiled function and thus fewer functions for the linker (and the compiler). Depending on options such as link-time code generation, this could matter quite a bit or hardly at all.
We found that template can greatly increase the compilation and link time. One of the problem is that each file that include the header declaring the template will have to parse it, check its validity, and if it is used by the compilation unit, the generated object file will contains the code, that will later be removed by the linker (if used by more than one file).
In our project, we had some large template, that were included in almost every file, but of which only two instantiation ever existed. We greatly improved the compilation time by using explicit instantiation, and separation of the template code in multiple files.
For your exemple, that would give you :
// MyClass.h
template < typename T >
class MyClass
{
void Print();
T m_tValue;
}
// MyClass.inl
#ifdef MY_CLASS_METHODS_ARE_NOT_INLINE
# define MY_CLASS_INLINE
#else
# define MY_CLASS_INLINE inline
#endif
template < typename T >
MY_CLASS_INLINE void MyClass< T >::Print()
{
std::cout << m_tValue << std::endl;
}
#undef MY_CLASS_INLINE
// MyClass.cpp
#include "MyClass.h"
#define MY_CLASS_METHODS_ARE_NOT_INLINE
#include "MyClass.inl"
template class MyClass< int >;
template void MyClass< int >::Print();
#undef MY_CLASS_METHODS_ARE_NOT_INLINE
It strictly depends on your toolchain (in this case at least linker and compiler, maybe more).
Just try, but be aware that results may vary a lot by changing even a single piece of your toolchain.