How does inlining work?

  • Thread starter Generic Usenet Account
  • Start date
G

Generic Usenet Account

While I have a very good feel for how inlining works, I fail to see how
in the world inlining can work if the inlined function is not described
"in place" in a header file, but rather defined in a separate source
file (using the inline keyword), which gets linked in? Does inling
work at all in such cases? If it does, can someone kindly explain how
the compilers handle that? If it does not, is that documented
somewhere?

Thanks,
Gus
 
D

David White

Generic said:
While I have a very good feel for how inlining works, I fail to see
how in the world inlining can work if the inlined function is not
described "in place" in a header file, but rather defined in a
separate source file (using the inline keyword), which gets linked
in? Does inling work at all in such cases? If it does, can someone
kindly explain how the compilers handle that? If it does not, is
that documented somewhere?

The definition of an inline function must be present and must be identical
in every translation unit (i.e., source file) in which it is called. If you
call an inline function in multiple source files the obvious way to do this
is to place the definition in a header file and #include the header in each
of the source files, but if you want, which you probably don't, you can
explicitly define the function separately and identically in each source
file.

I sometimes place an inline function in a source file rather than a header
file if I don't use it anywhere else (e.g., a private class member
function).

DW
 
G

Greg

Generic said:
While I have a very good feel for how inlining works, I fail to see how
in the world inlining can work if the inlined function is not described
"in place" in a header file, but rather defined in a separate source
file (using the inline keyword), which gets linked in? Does inling
work at all in such cases? If it does, can someone kindly explain how
the compilers handle that? If it does not, is that documented
somewhere?

Thanks,
Gus

No, the inline keyword alone is not enough to let a function call be
inlined.

In order to inline a function the compiler must also have the
function's implementation on hand. For this reason inline functions are
declared in header files. If the compiler has not seen the inlined
function's body when it compiles a call to that function, the function
call will not be inlined.

Failing to inline a function call is not considered an error; generally
there wil be no indication that a function call was not inlined. But
most C++ compilers have a setting to report an error whenever the
compiler was unable to inline a function.

Greg
 
A

Alf P. Steinbach

* Generic Usenet Account:
While I have a very good feel for how inlining works,

Uh, you don't. ;-)

I fail to see how
in the world inlining can work if the inlined function is not described
"in place" in a header file, but rather defined in a separate source
file (using the inline keyword), which gets linked in?

That is not allowed.

Does inling work at all in such cases?

If you remove the 'inline' keyword so as to get a conforming program text,
then yes, it can work. That's called "whole program optimization", or "global
optimization". For example, Visual C++ from Microsoft does this.

If it does, can someone kindly explain how the compilers handle that?

Generally it's the linker that takes care of this job, because only the linker
has the necessary information available. If or when we get modules into the
language, possibly in C++0x, the compiler may be able to contribute more. Or
not, depending on how the standardization process turns out.

If it does not, is that documented somewhere?

If you mean, whether your invalid use of the 'inline' keyword is documented as
invalid anywhere, then that's the C++ standard. If you mean, is whole program
optimization documented somewhere, that'll be your compiler's documentation.
 
N

Nimmi Srivastav

Alf said:
That is not allowed.

I disagree. This is most certainly allowed by most compilers ----
whether it works or not as desired is a different issue altogether!

Thanks,
Nimmi
 
A

Alf P. Steinbach

* Nimmi Srivastav:
I disagree.

Seemingly you don't understand that this is a matter of _fact_, as opposed to
a matter of opinion. So, cough up chapter and verse from the standard.
 
P

persenaama

So, cough up chapter and verse from the standard.

I thought you knew already where in the standard that is as it looks
like you just read the chapter and verse carefully no doubt.

To Nimmi: please can you give a quote too as I'm handicapped by lack of
the standard document at the moment as I didn't have the foresight to
copy the file to my laptop before traveling. :)

I don't remember it being undefined to have inline specifier in
function or method declaration, but then again, the standard is over
700 pages.. <- sorry, I am just a human being and not have a perfect
memory STILL I work writing software sometimes in c++, does that make
_me_ incompetent? Should I resign now? Anyway, since the topic popped
up curious to get the topic laid to rest with facts. Thanks guys,
whoever helps me first. ;----)
 
D

David White

persenaama said:
I thought you knew already where in the standard that is as it looks
like you just read the chapter and verse carefully no doubt.

To Nimmi: please can you give a quote too as I'm handicapped by lack of
the standard document at the moment as I didn't have the foresight to
copy the file to my laptop before traveling. :)

* * * * *
7.1.2
2 A function declaration (8.3.5, 9.3, 11.4) with an inline specifier
declares an inline function. The inline specifier indicates to the
implementation that inline substitution of the function body at the point of
call is to be preferred to the usual function call mechanism. An
implementation is not required to perform this inline substitution at the
point of call; however, even if this inline substitution is omitted, the
other rules for inline functions defined by 7.1.2 shall still be respected.

3 A function defined within a class definition is an inline function. The
inline specifier shall not appear on a block scope function declaration.(79)

4 An inline function shall be defined in every translation unit in which it
is used and shall have exactly the same definition in every case (3.2).
[Note: a call to the inline function may be encountered before its
definition appears in the translation unit. ] If a function with external
linkage is declared inline in one translation unit, it shall be declared
inline in all translation units in which it appears; no diagnostic is
required. An inline function with external linkage shall have the same
address in all translation units. A static local variable in an extern
inline function always refers to the same object. A string literal in an
extern inline function is the same object in different translation units.
* * * * *

The reference to external linkage doesn't make sense to me yet. TC++PL 3rd
Ed. says (p. 199) that the "combination of external linkage and inlining is
banned to make life simpler for compiler writers:"
// file1.c:
extern inline int g(int i);
int h(int i) { return g(i); } // error: g() undefined in this
translation unit
// file2.c
extern inline int g(int i) { return i+1; }
I don't remember it being undefined to have inline specifier in
function or method declaration, but then again, the standard is over
700 pages.. <- sorry, I am just a human being and not have a perfect
memory STILL I work writing software sometimes in c++, does that make
_me_ incompetent? Should I resign now? Anyway, since the topic popped
up curious to get the topic laid to rest with facts. Thanks guys,
whoever helps me first. ;----)

DW
 
P

persenaama

Thanks for the quote, it takes a couple of readings to decrypt what
they intended to say, actually I still didn't quite get what their
*intention* was but according to these rules what mr. Stenbach says is
not strictly incorrect.. as long as the *definition* is inline in every
translation init all's well as far as the standard is concerned.

Quote from the quote (thanks!): "If a function with external
linkage is declared inline in one translation unit, it shall be
declared
inline in all translation units in which it appears; no diagnostic is
required."

The keyword here is *declared*, declared.. that will hold up true
indeed if the same header is included in other translation units (note:
I am not claiming that files or headers exist they are just figment of
implementations imagination ;-) So far so good, the original poster's
hypothesis (?) doesn't invalidate this rule..

Earlier in the same paragraph this is stated:

"4 An inline function shall be defined in every translation unit in
which it
is used and shall have exactly the same definition in every case
(3.2)."

Indeed, if the *definition* is in other translation unit, in this case
I read between the lines that in a different sourcefile (okay, again,
implementation specific detail but that's how I interpreted the
original post, call me incompetent ;) So far again I don't see any
gross neglegance or violation of the standard in the original post,
just construct which requires every other translation unit to have the
*same* definition, this is rather difficult to enforce unless the same
sourcecode is part of the other translation units being compiled. The
common method to achieve this is to put the inline code in a header
file, often the declaration and definition are the same thing.. or the
definition comes later in the same file, or, separate implementation
file is used, .inl is what I encountered myself now and then (not my
sourcecode heaven's sake, I combine the definition with declaration
more often than not :)

All in all, I don't seem to see where the actual error is, I only see
where it could possibly be but w/o any actual sourcecode to discuss..

The example you posted is a good case, btw. Side effects, linkage,
undefined behaviour and such aside, one way I can see this could be
implemented without much fuss is that the compiler merely ignores the
inline keyword. It's free to do so at any time of it's liking for code
generation purposes anyhow. The only difficulty is that the standard
itself disagrees (?) with the TC++PL.. I'd say I'd trust the standard
more in this case as that's what all implementations are supposed to be
implementing (?) I'm very likely to be wrong since I am way out of my
league here.. but I got asshole and I got opinions and this is a
discussion group so there! ;-)
 
M

msalters

persenaama schreef:
Thanks for the quote, it takes a couple of readings to decrypt what
they intended to say, actually I still didn't quite get what their
*intention* was but according to these rules what mr. Stenbach says is
not strictly incorrect.. as long as the *definition* is inline in every
translation init all's well as far as the standard is concerned.

You are aware that every definition is also a declaration? There's
no word for declarations-that-aren't-definitions, although "forward
declaration" comes close.

The only difficulty is that the standard
itself disagrees (?) with the TC++PL.. I'd say I'd trust the standard
more in this case as that's what all implementations are supposed to be
implementing (?)

Assuming you have a 3rd ed, there is no disagreement. And yes,
implementations are supposed to implement the standard. Mr. Stroustrup
has very good ideas, but he isn't the ultimate authority.

HTH,
Michiel Salters
 
A

Alf P. Steinbach

* persenaama:
Thanks for the quote, it takes a couple of readings to decrypt what
they intended to say, actually I still didn't quite get what their
*intention* was but according to these rules what mr. Stenbach says is
not strictly incorrect..

If I'd adopted the practice of plonking, you'd now be plonked.
 
P

persenaama

You are aware that every definition is also a declaration?

If that wasn't the case we would need to have forward declaration
always to go with every definition, which isn't true unless the
definition comes later in the translation unit where there are
instances of calls to the function. In short: yes, ofcourse.
There's no word for declarations-that-aren't-definitions, although "forward
declaration" comes close.

class foo;

class foo {
public:
int bar(int);
};

inline int foo::bar(int x) { return x + 1; }

Let's get the record straight, I assumed the OP meant this concept:

// file 1 (say, foo.h)
inline int foo(int);

// file 2 (say, foo.cpp)
inline int foo(int x) { return x + 1; }

That is not allowed? I can think easily of cases where that is fully
legal and allowed: if both files are part of the SAME TRANSLATION UNIT
the correctness is easy to guarantee without further consultation to
the standard (speaking only for myself :)
 
E

E. Robert Tisdale

Generic said:
While I have a very good feel for how inlining works,
I fail to see how in the world inlining can work
if the inlined function is not described "in place" in a header file
but, rather, defined in a separate source file (using the inline keyword)
which gets linked in?

The inline qualifier doesn't really have anything to do with inlining --
it's about linkage. For example:
> cat main.cc
#include <iostream>

inline
void f(void) {
std::cout << "f(void)" << std::endl;
}

void g(void (*p)());

int main(int argc, char* argv[]) {
g(f);
return 0;
}
> g++ -Wall -ansi -pedantic -c main.cc
> nm --demangle main.o
U __cxa_atexit
U __dso_handle
00000090 t global constructors keyed to main
U __gxx_personality_v0
00000000 T main
00000034 t __tcf_0
00000000 W f()
U g(void (*)())
.
.
.

As you can plainly see,
the compiler leaves behind a "weak" symbol
for the copy of f(void) that is generated
so that it could pass a pointer to g(void (*)()).

If I had not labeled f(void) inline:
> cat main.cc
#include <iostream>

void f(void) {
std::cout << "f(void)" << std::endl;
}

void g(void (*p)());

int main(int argc, char* argv[]) {
g(f);
return 0;
}
> g++ -Wall -ansi -pedantic -c main.cc
> nm --demangle main.o
U __cxa_atexit
U __dso_handle
000000be t global constructors keyed to _Z1fv
U __gxx_personality_v0
0000002e T main
00000062 t __tcf_0
00000000 T f()
U g(void (*)())
.
.
.

the compiler would have left behind a symbol for f(void)
which could confuse the link editor
if it found the same symbol defined in another object file.
Does inlining work at all in such cases?

It is implementation dependent.
Common sense will tell you that
a function definition (whether labeled inline or not)
*must* be visible to the compiler
when it encounters the function invocation.
Some compilers (especially Fortran compilers)
will search through source files for function definitions
that they can inline but most C and C++ compilers
require the inline function to be included
in the translation unit where they are invoked.
If it does, can someone kindly explain how the compilers handle that?

I don't know of any C or C++ compilers
that search specifically for inline function definitions
but several implementations allow you to create, maintain and search
repositories which contain function template definitions.
Unfortunately, the standards say nothing about these repositories
and probably can't say anything about them that would be helpful
to either compiler developers or programmers.
If it does not, is that documented somewhere?

Try the man pages for your C++ compiler.
But, if you want your code to be portable,
you should arrange to have inline function definitions
included in every translation unit where they are invoked.
 
D

Dave Rahardja

Quote from the quote (thanks!): "If a function with external
linkage is declared inline in one translation unit, it shall be
declared
inline in all translation units in which it appears; no diagnostic is
required."

The keyword here is *declared*, declared.. that will hold up true
indeed if the same header is included in other translation units
Yes.


"4 An inline function shall be defined in every translation unit in
which it
is used and shall have exactly the same definition in every case
(3.2)."

Indeed, if the *definition* is in other translation unit, in this case
I read between the lines that in a different sourcefile (okay, again,
implementation specific detail but that's how I interpreted the
original post, call me incompetent ;)

The notion of a "translation unit" is _not_ implementation specific.

From 2.1:

A source file together with all the headers (17.4.1.2) and source files
included (16.2) via the preprocessing directive #include, less any source
lines skipped by any of the conditional inclusion (16.1) preprocessing
directives, is called a translation unit.


Header files, .inl files, whatever you #include in your source file becomes
part of the translation unit.


So far again I don't see any
gross neglegance or violation of the standard in the original post,
just construct which requires every other translation unit to have the
*same* definition, this is rather difficult to enforce unless the same
sourcecode is part of the other translation units being compiled. The
common method to achieve this is to put the inline code in a header
file, often the declaration and definition are the same thing.. or the
definition comes later in the same file, or, separate implementation
file is used, .inl is what I encountered myself now and then (not my
sourcecode heaven's sake, I combine the definition with declaration
more often than not :)

Please keep stream-of-consciousness prose out of messages as it makes your
questions and assertions difficult to find. Write after you're done thinking,
not while you're thinking.


All in all, I don't seem to see where the actual error is, I only see
where it could possibly be but w/o any actual sourcecode to discuss..

The OP wanted to know if it is indeed true that you have to define an inline
function in every translation unit. And the answer is: only if you use it in
that translation unit.


The example you posted is a good case, btw. Side effects, linkage,
undefined behaviour and such aside, one way I can see this could be
implemented without much fuss is that the compiler merely ignores the
inline keyword.

No. The Standard enforces the recognition of the inline keyword as part of the
function specification, even if the compiler doesn't do any inlining.

From 7.1.2.2:

An implementation is not required to perform this inline substitution at the
point of call; however, even if this inline substitution is omitted, the other
rules for inline functions defined by 7.1.2 shall still be respected.

The only difficulty is that the standard
itself disagrees (?) with the TC++PL..

How do they disagree?


but I got asshole and I got opinions and this is a
discussion group so there! ;-)

Your right to free speech does not infringe on my right not to listen.

-dr
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top