Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to separate the two meanings of the "inline" keyword (ODR relaxation vs. function code inlining)

Tags:

c++

I think I fully understand the meaning of the inline keyword in C++. Specifically it means two only semi-related things:

  1. The ODR rule is relaxed for the function declared 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.
  2. It is a suggestion to the compiler that it should replace invocations of the functions with a copy of the function's compiled code, rather than a 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!

like image 391
David Stone Avatar asked Dec 16 '18 17:12

David Stone


1 Answers

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.

like image 97
eerorika Avatar answered Oct 23 '22 05:10

eerorika