Sum up the effects of "inline"?

F

Frederick Gotham

The original purpose of "inline" was that code could be "expanded in
place". Of course, it has other uses...

For one thing, the following two translation units will compile together
succesfully into a program:

/* source1.cpp */

inline int Func(double arg)
{
static double d = 0.;

return d += arg;
}

int main()
{
Func( 24.333);
}


/* source2.cpp */

inline int Func(double arg)
{
static double d = 0.;

return d += arg;
}


Here, "inline" alleviates our need to abide by the "One Definition Rule".

I have two questions though:

(1) What would be the effect of putting "extern" or "static" before
an inline function? Do inline functions have internal linkage, external
linkage, or neither?

(2) Template functions too seem to alleviate our need to abide by the
"One Definition Rule". Is this true? What would be the effect of putting
"inline", "extern" or "static" before a template function?
 
C

Chandu

Here, "inline" alleviates our need to abide by the "One Definition Rule".

No, becoz the body gets substituted as if there is no function.
(1) What would be the effect of putting "extern" or "static" before
an inline function? Do inline functions have internal linkage, external
linkage, or neither?

Read C++-FAQs.
(2) Template functions too seem to alleviate our need to abide by the
"One Definition Rule". Is this true?

NO, template functions gives u different functions upon instantiations.
What would be the effect of putting
"inline", "extern" or "static" before a template function?

compiler error
 
N

Noah Roberts

Frederick said:

Wow, remind me never to help you.
Four wrong answers, each answered with a more authoritive tone than the
last.

Actually, one answer that is dubious, one that is incorrect, one that
is correct, and a suggestion that did not answer any question.
I think this is my first time using a killfile.

You're well on your way.
 
F

Frederick Gotham

Frederick Gotham posted:

(1) What would be the effect of putting "extern" or "static"
before
an inline function? Do inline functions have internal linkage,
external linkage, or neither?


Okay I've done some experimenting.

My conclusions are as follows:

(1) "inline" functions have external linkage by default.

(2) Placing "extern" before an inline function has no effect, because
it's already "extern" by default.

(3) Placing "static" before an inline function, however, certainly does
have an effect -- but I think the effect is only noticable if the inline
function contains static local objects.

Could someone please confirm that these assertions are right?

I have come across an interesting scenario however, involving an extern
inline function. Here's a short program consisting of three files:

/* header.hpp */

#ifndef INCLUDE_HEADER_HPP
#define INCLUDE_HEADER_HPP

inline int InlineFunc()
{
return ++val; /* Alters a global variable */
}

#endif

/* END OF header.hpp */


/* main.cpp */

static int val = 0;

#include "header.hpp"


void FuncInOtherFile();


#include <iostream>

int main()
{
FuncInOtherFile();

std::cout << InlineFunc() << '\n';
}

/* END OF main.cpp */


/* OtherFile.cpp */

static int val = 0;

#include "header.hpp"

void FuncInOtherFile()
{
InlineFunc();
}

/* END OF OtherFile.cpp */


Is there anything in the Standard which forbids an extern inline function
from accessing a global static object? Judging by the above program, it
appears to me that there should be such a restriction. (However no such
restriction would be necessary for a static inline function).
 
F

Frederick Gotham

Frederick Gotham posted:

(2) Template functions too seem to alleviate our need to abide by
the
"One Definition Rule". Is this true? What would be the effect of
putting "inline", "extern" or "static" before a template function?


I have experimented with template functions aswell. My conclusions are as
follows:

(1) A template function has external linkage by default.
(2) Placing "extern" before it has no effect, because it's already
extern by default.
(3) Placing "static" before it gives it internal linkage, and has a
noticable effect if the function contains static local objects.
(4) Placing "inline" before a template function has no effect other
than to ask the compiler to expand the code in-place.


Okay... so I've learned something. I'll go experiment with "export" now.
 
B

Bo Persson

Frederick Gotham said:
Frederick Gotham posted:




Okay I've done some experimenting.

My conclusions are as follows:

(1) "inline" functions have external linkage by default.

(2) Placing "extern" before an inline function has no effect,
because
it's already "extern" by default.

(3) Placing "static" before an inline function, however,
certainly does
have an effect -- but I think the effect is only noticable if the
inline
function contains static local objects.

Could someone please confirm that these assertions are right?

I have come across an interesting scenario however, involving an
extern
inline function. Here's a short program consisting of three files:

/* header.hpp */

#ifndef INCLUDE_HEADER_HPP
#define INCLUDE_HEADER_HPP

inline int InlineFunc()
{
return ++val; /* Alters a global variable */
}

#endif

/* END OF header.hpp */


/* main.cpp */

static int val = 0;

#include "header.hpp"


void FuncInOtherFile();


#include <iostream>

int main()
{
FuncInOtherFile();

std::cout << InlineFunc() << '\n';
}

/* END OF main.cpp */


/* OtherFile.cpp */

static int val = 0;

#include "header.hpp"

void FuncInOtherFile()
{
InlineFunc();
}

/* END OF OtherFile.cpp */


Is there anything in the Standard which forbids an extern inline
function
from accessing a global static object? Judging by the above program,
it
appears to me that there should be such a restriction.

No, there are not.

There are however rules against including the header files so that
different 'val' variables are visible to the function definitions.
That is a violation of the One Definition Rule.

(However no such
restriction would be necessary for a static inline function).

In that case they are technically different functions, that just
happen to have the same name. This is ok, as they are local functions
in different compilation units.


Bo Persson
 
F

Frederick Gotham

Frederick Gotham posted:
Okay... so I've learned something. I'll go experiment with "export"
now.


I've always thought of "external linkage of a function" implying two
things:

(1) The function can be invoked from inside a different source file,
even though the other source file only contains a declaration of the
function, rather than a definition.
(2) If an external linkage function contains static local objects,
they're shared by the entire program (rather than having a unique set of
static objects for each translation unit).

An ordinary template function such as the following has external linkage:

template<class T>
extern T TemplateFunc()
{
static T val = 0;

return ++val;
}

(The "extern" is superfluous, and so it can be written simply as:)

template<class T>
T TemplateFunc()
{
static T val = 0;

return ++val;
}


Given that the template function immediately above has external linkage,
it satisfies point (2) which I mention above. However, it doesn't satisfy
point (1), as demonstrated by the following program:


/* main.cpp */

template<class T>
T TemplateFunc();

int main()
{
TemplateFunc<int>();
}


/* otherfile.cpp */

template<class T>
T TemplateFunc()
{
static T val = 0;

return ++val;
}


So it doesn't seem quite fitting to say that a template function has
"external linkage", because it doesn't satisfy point (1) that I mention
at the beginning of this post.

It seems to me that if you want a template function to have TRUE external
linkage, then you have to define it as "export". Unfortunately I don't
have a compiler which supports "export", so I can't test it.
 
S

Steve Pope

Frederick Gotham said:
I've always thought of "external linkage of a function" implying two
things:

(1) The function can be invoked from inside a different source file,
even though the other source file only contains a declaration of the
function, rather than a definition.
(2) If an external linkage function contains static local objects,
they're shared by the entire program (rather than having a unique set of
static objects for each translation unit).

Under what conditions would a static object declared within
a function exist separately for each translation unit specifically?

Steve
 
F

Frederick Gotham

Steve Pope posted:

Under what conditions would a static object declared within
a function exist separately for each translation unit specifically?


Here's a little program for you. It consists of three files, a header and
two source files.

The header file contains a vanilla inline function.

/* header.hpp */

#ifndef INCLUDE_HEADER_HPP
#define INCLUDE_HEADER_HPP

inline unsigned InlineFunc()
{
static unsigned i = 0;

return ++i;

}

#endif


/* a.cpp */

#include "header.hpp"

void FuncInOtherFile();

#include <iostream>

int main()
{
FuncInOtherFile();

std::cout << InlineFunc() << '\n';

std::getchar();
}


/* b.cpp */

#include "header.hpp"

void FuncInOtherFile()
{
InlineFunc();
}


Run the program and see what output you get.

Then change the inline function to "static", re-compile, and see what
output you get. (Some compilers might need you to "Rebuild All" because
they don't notice that the header has been changed...)

The moral of the story is that there's more than one function. There's
the static function in "a.cpp", and there's the static function in
"b.cpp", and they're unrelated as far as the compiler and linker are
concerned.
 
F

Frederick Gotham

Frederick Gotham posted:

std::getchar();


Ignore that statment.

(I'm running the broken Operating System known as Windows XP, and I have to
stick that at the end of my programs so that I can see the output before
the console window disappears.)
 
S

Steve Pope

Frederick Gotham said:
Steve Pope posted:
Here's a little program for you. It consists of three files, a
header and two source files.

Yes, okay if the entire function is also declared static, then
its static objects exist separately in each translation unit.

Hadn't thought of that. Any other conditions, or is this it?

Steve
 
F

Frederick Gotham

Steve Pope posted:

Yes, okay if the entire function is also declared static, then
its static objects exist separately in each translation unit.


A better way of looking at it would be like this -- we don't have one
"entire function", but rather two, and the translation units look like
the following after they've gone through the preprocessor:

/* a.cpp */

static int Func()
{
static int i = 0;

return ++i;
}

int main() {}


/* b.cpp */

static int Func()
{
static int i = 0;

return ++i;
}


As you can see, each function is "private" to each translation unit, and
neither translation unit is aware that the other translation unit
contains a "private" function by the same name.

Because we have the function typed out once in a header file, we might
think of it as ONE function -- but it's NOT... it's two unrelated
functions once it's passed through the preprocessor.


Hadn't thought of that. Any other conditions, or is this it?


The only one I can think of.
 
S

Steve Pope

Frederick Gotham said:
Steve Pope posted:
A better way of looking at it would be like this -- we don't have one
"entire function", but rather two, and the translation units look like
the following after they've gone through the preprocessor:
/* a.cpp */

static int Func()
{
static int i = 0;

return ++i;
}

int main() {}


/* b.cpp */

static int Func()
{
static int i = 0;

return ++i;
}
As you can see, each function is "private" to each translation unit, and
neither translation unit is aware that the other translation unit
contains a "private" function by the same name.
Because we have the function typed out once in a header file, we might
think of it as ONE function -- but it's NOT... it's two unrelated
functions once it's passed through the preprocessor.

Yes, simple enough if you've programmed in C for years and
this was one of the few encapsulation methods available to you. ;-)


Steve
 
R

Ron Natalie

Frederick said:
Here, "inline" alleviates our need to abide by the "One Definition Rule".

All inline syntactically does is modify the restriction that things are
defined only once. It allows multiple inclusion of syntactically
identical copies of the same function.

Semantically it's just a hint.
 

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,774
Messages
2,569,596
Members
45,144
Latest member
KetoBaseReviews
Top