What are the best practices for the FORCELINE macro?
My understanding of standard inline keyword is that it requests that the compiler inlines the contents of a function, that is, copied and pasted. And that the compiler might ignore the inline request for optimization reasons. And the Unreal FORCELINE macro is meant to make sure the compiler does indeed inline the function.
I have seen people use FORCEINLINE for Getters and Setters defined in the header file. But I was wondering about other use cases:
For instance, can I use FORCELINE for function extractions to improve code readability, without the overhead cost of actually creating another function call, since the compiler copy/past the code inline before execution.
I am thinking of cases like long and verbose if statements that can be simplified to: if (InlineFunction()) { }
Or to hide away multiple lines of code with a descriptive function name, rather than using comments.
I realize that the overhead of having many smaller function calls is generally not a concern; but my concern/interest is in regard to extracting complex code into many small functions for neatness and readability, without the trade off of these many function calls potentially jumping around memory, for code that happens each frame?
Or should I not do this for some reason I am not aware of?
Also, if the function declaration and implementation are separated into a header and .cpp file, do I need specify the FORCELINE at both the declaration and implementation?
I absolutely can’t tell you what best practices are, but I can share my opinion.
Which may be a controversial take to be posting on this forum, but I am feeling brave today so here goes…
How should FORCEINLINE macro by used in C++?
It shouldn’t be used at all.
Also, if the function declaration and implementation are separated into a header and .cpp file, do I need specify the FORCELINE at both the declaration and implementation?
If the definition is only in one translation unit, the compiler could only inline it in that translation unit. This is actually what the regular inline keyword is/was for, it allows you to define it in multiple translation units (normally a link time multiple def error) so it can be inlined there (if the compiler decides so).
You should not worry about actually doing this though (and hopefully the thought of having multiple definition for the same function in different translation units makes you uncomfortable, at the least), link time optimisations will do this for you anyway.
This old post What is FORCEINLINE macro? - #2 by Shadowriver suggests FORCEINLINE does indeed do as it says on Windows, presumably still true, but if you think you can decide better than the compiler, I can assure you that you are almost certainly wrong. If profile guided optimisation is also in use, no human stands any chance of competing.
For the example of the if conditions you gave, do what you feel is best for you (hide it in a function, presumably), and don’t worry about optimisation… the compiler/linker will do it for you if it will be benificial.
That’s my take on it anyway. To anyone who holds different view, please post! OP will be intersted in what you have to say, as will I.
Do you think I should be using the standard inline keyword instead, or simply trust the compiler to optimize inline functions without me requestion it be inline?
In the context of actually inlining code, inline was only ever a hint the compiler was free to ignore, and as I understand it modern compilers almost universally ignore it completely.
I would trust the compiler myself, low level optimisation is hard and the compiler will do it better anyway, your better off optimising at a higher level: choice of data-structures and the algorithms that operate on them, finding ways to not call functions at all (rather than trying to remove the call overhead), things the compiler can’t do for you.
If you really want to control this yourself, FORCEINLINE would be the way to go, inline will do nothing.