Inlines with external linkage

A

Andre Kostur

JKop said:
But didn't some-one say that inline functions are allowed a multiple
definition?

Read section 3.2(5) of the Standard. Of particular interest is that
"inline function with external linkage" is permitted to have multiple
definitions, with certain restrictions, the most important in this case
is "each definition of D shall consist of the same sequence of tokens".

Your example violates that condition, thus you have undefined behaviour.
Is a C++ Standard compliant compiler allowed to compile whatever it
likes? For instance can it compile the following without giving any
errors at all?:

Not quite. There are certain things that require diagnostics and some
that don't.
#include <int main()
{
#include <iostream> chocolate;

++chocolate++ = 54;

return inline; ? 6 :? cout << "Hello World";>

I'd get a different compiler if it did that without a diagnostic.. but
that's a Quality of Implementation issue, not a Standard issue.
If so, then yes, my sample code does in fact have a Multiple
Definition. Deductive Reasoning:

1) Multiple Definitions are Undefined Behaviour.

Imprecise definitions. Depends on what you mean by "Multiple
Definitions". If you have the _same_ sequence of tokens for an inline
with external linkage in two different translation units, is that a
"Multiple Definition"? If so, then this premise is not universally true.
2) My code contains Multiple Definitions.
Yes

3) My code contains Undefined Behaviour.
Yes

What I would absolutely love an explanation to is this, why does the
following not compile:


int Yum(char)
{
std::cout << "monkey!";

return 't';
}

int Yum(char)
{
std::cout << "ape!";

return 'k';
}

Those two are simply functions (which falls under Section 3.2(3))
while the following does:


inline int Yum(char)
{
std::cout << "monkey!";

return 't';
}

inline int Yum(char)
{
std::cout << "ape!";

return 'k';
}

These are inline functions with external linkage (which falls under
Section 3.2(5)).
Is it:

A) Because Standard C++ allows multiple definitions of inline
functions. If so, then my code is *not* undefined behaviour, as
there's nothing undefined about multiple defining an inline function.

Depending on your definition of "multiple definitions". Multple places
where you specify the body of the function? Yep it's allowed. As long
as the two bodies are the same sequence of tokens.
B) Because g++ is shit?

You seem to be fixated on something.....
 
J

JKop

Andrey Tarasevich posted:
"Chapter and verse" was named here on numerous occasions. However, you
chose to ignore it. How is this time different? Anyway, 7.1.2/2 clearly
states that an inline function with external linkage must be declared
'inline' in every translation unit in which it appears. It also says
that it shall be _defined_ in every translation unit in which it is
used. The standard says nothing about the behavior in situations when
the above requirements are violated. This is undefined behavior, by
definition of 'undefined behavior' given in 1.3.12.

Take out cow.cpp and omit the function call to "cow" from main, and then I
no longer violate the above. But that still doesn't clarify whether ape()
calls Yum from yum.hpp or yummy.hpp.

If an inline function shall be defined in every translation unit in which it
is used, then why does it have external linkage?


-JKop
 
H

Howard

Andre Kostur said:
... As long
as the two bodies are the same sequence of tokens.

What does that mean, exactly? That the function definitions (bodies) must
be identical (after ignoring white space)? If that's what you're saying,
then I'm confused, because the bodies of those two functions were different.
(One output "monkey" and returned 't', while the other output "ape" and
returned 'k'.)

-Howard
 
A

Andrey Tarasevich

JKop said:
Take out cow.cpp and omit the function call to "cow" from main, and then I
no longer violate the above. But that still doesn't clarify whether ape()
calls Yum from yum.hpp or yummy.hpp.

I didn't intend to re-type the standard word-to-word in my previous
message, so I omitted some things. (Why don't you just take the document
and read it yourself?). The important thing in this case is that inline
function shall be _defined_ in every translation unit in which it is
used and that it should be defined _identically_ in all those
translation units (see 7.1.2/4). If you get rid of 'cow.cpp', you'll
still have 'main.cpp' and 'ape.cpp' both of which contain a definition
of an inline function 'Yum' with external linkage and these definitions
are different from each other. That's a direct violation of requirements
stated in 7.1.2/4.
If an inline function shall be defined in every translation unit in which it
is used, then why does it have external linkage?

Why not? As I said several times before, apparently you understand
"having external linkage" as "being linkable through a simple extern
declaration from another translation unit". This is not a correct
understanding. The notion of "having external linkage" applies to a lot
of different entities in the language (types, for example, also have
linkage in C++) and means a lot of different things. Some of these
things are not applicable to inline functions, some are applicable. For
example, one thing that applies to inline functions is that an inline
function with external linkage is guaranteed to have the same address in
every translation unit (also remember that thing with local static
variables etc.). If you care about these guarantees, you should declare
your function with external linkage. Otherwise, declare it with internal
linkage if you wish.
 
A

Andre Kostur

What does that mean, exactly? That the function definitions (bodies)
must be identical (after ignoring white space)? If that's what you're
saying, then I'm confused, because the bodies of those two functions
were different. (One output "monkey" and returned 't', while the other
output "ape" and returned 'k'.)

.... you'd have to read the Standard to get all the picky details, but my
understanding of it is that the two functions have to be basically
identical. If they're not, you've wandered over into Undefined Behaviour.
Which is why JKop's programs are "bad".
 
J

JKop

Andre Kostur posted:
Read section 3.2(5) of the Standard. Of particular interest is that
"inline function with external linkage" is permitted to have multiple
definitions, with certain restrictions, the most important in this case
is "each definition of D shall consist of the same sequence of tokens".

What in the name of whipped ice-cream, dipped in 100s 'n' 1,000s, oozed with
red syrup is "the same sequence of tokens"?

Does it mean the exact same code?


-JKop
 
J

JKop

The C++ Programming Language 3rd Edition by Bjarne Stroustrup page 199,
section 9.2:

An inline function must be defined - by identical definitions - in every
translation unit in which it is used. Consequently, the following example
isn't just bad taste; it is illegal:

// file1.c:
inline int f(int i) { return i; }

// file2.c:
inline int f(int i) { return i + 1; }

Unfortunately, this error is hard for an implementation to catch, and the
following - otherwise perfectly logical - 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; }


By default, consts and typedefs have internal linkage. Consequently this
example is legal (although potentially confusing):


// file1.c
typedef int T;
const int x = 7;

// file2.c
typedef void T;
const int x = 8;


Global variables that are local to a single compilation unit are a common
source of confusion and are best avoided. To ensure consistency, you should
usually place global consts and inlines in header files only.
A const can be given external linkage by an explicit declaration:


// file1.c:
extern const int a = 77;

// file2.c:
extern const int a;

void g()
{
cout << a << '\n';
}


Here, g() will print 77.


-JKop
 

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,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top