Even with __forceinline, the compiler cannot inline code in all circumstances. The compiler cannot inline a function if:
*The function or its caller is compiled with /Ob0 (the default option for debug builds).
*The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).
*The function has a variable argument list.
*The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.
*The function returns an unwindable object by value, when compiled with /GX, /EHs, or /EHa.
*The function receives an unwindable copy-constructed object passed by value, when compiled with /GX, /EHs,, or /EHa.
*The function is recursive and not accompanied by #pragma inline_recursion(on). With the pragma, recursive functions can be inlined to a default depth of eight calls. To change the inlining depth, use inline_depth pragma.
*The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.
*The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.
*The function is also marked with the naked __declspec modifier.
If the compiler cannot inline a function declared with __forceinline, it generates a level 1 warning (4714).
The inline keyword tells the compiler that inline expansion is preferred. However, the compiler can create a separate instance of the function (instantiate) and create standard calling linkages instead of inserting the code inline. Two cases where this can happen are:
*Functions that are referred to through a pointer elsewhere in the translation unit.
These reasons may interfere with inlining, as may others, at the discretion of the compiler; you should not depend on the inline specifier to cause a function to be inlined.
Note that for a function to be considered as a candidate for inlining, it must use the new-style function definition. Functions that are declared as inline, and that are not class member functions, have internal linkage unless otherwise specified.
As with normal functions, there is no defined order of evaluation of the arguments to an inline function. In fact, it could be different from the order in which the arguments are evaluated when passed using normal function call protocol.
The /Ob compiler optimization option helps to determine whether inline function expansion actually occurs.