I think I fully understand the meaning of the inline
keyword in C++. Specifically it means two only semi-related things:
inline
. Thus you can have the same function symbol defined in multiple TUs without getting an error when linking them. This allows a function to be defined in a header.call
instruction to the address of the function symbol.I can understand that these two meanings are necessarily related in one direction: 2 must imply 1. #2 requires that the function definition be available to all TUs that invoke the function. Therefore the function definition must exist in multiple TUs. Therefore the ODR needs to be relaxed to avoid linker errors.
But my question is about the other direction - why is the language designed such that 1 must imply 2?
It seems reasonable, in some cases and for some design decisions, to want to be able to relax the ODR for a function, without suggesting to the compiler that it should actually inline the function code. If I have a function I want to distribute via a header file I must mark it as inline
to relax the ODR (#1). But now I am forced into #2 even if I have specific knowledge that in terms of performance, the function is not a good candidate for inlining.
My understanding is that this unwanted implication does not exist for template functions. The ODR is automatically relaxed for template functions (as it must be). That allows me to use inline
only as a performance suggestion.
I understand that distributing functions in header files, as opposed to e.g. a static library, can be a bad idea. But as a programmer, there is some possibility that I know what I am doing, and I would like that flexibility. I have that flexibility with template functions so why not non-template functions?
Or is there a portable way to relax the ODR without suggesting that the function be inlined? E.g. on MSVC you can do this:
__declspec(noinline) inline void Foo() {}
Here inline
relaxes the ODR, but __declspec(noinline)
requests that the compiler not actually inline the call. But __declspec(noinline)
isn't portable.
Thanks!
But
__declspec(noinline)
isn't portable.
You can make it portable to all implementations that have an analogous attribute by using a platform detection macro. GCC and Clang have __attribute__((noinline))
.
Another approach is to simply not care. The compiler still has the option to ignore the preference that it perceives to have been implied. If the inline expansion would be expensive (because the function is big), a smart compiler should refrain from expanding it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With