Linker Role for Multiple Template class Object Instantiation

P

Pallav singh

HI

How does linker resolve multiple copy of template class object ,
Instantiated in different files ?
How it chooses object location from given N object location ?
What id criteria on which selection is Made ?
what happen to other object memory Locations ?

Thanks
Pallav Singh
 
J

Juha Nieminen

Pallav singh said:
How does linker resolve multiple copy of template class object ,
Instantiated in different files ?

"Template class object" would mean the same thing as "an instance of a
class (which happens to be a template class)". Class instances follow the
same rules as variables.

But I don't think that's what you were asking. You were probably asking
about the *member functions* of template classes. Since they can be and often
are instantiated in several compilation units, the linker will find several
instances of the same function implementation.

This is no different from regular template functions and inline
functions (which aren't inlined). In fact, template functions (and
membmer functions) are actually declared 'inline' implicitly, so they
work in the exact same way as regular inline functions.

When a function has been declared 'inline' and the linker finds several
instances of it, it will use just one of them and make all the code call
that one. Which one it chooses (or how) is not specified. Only one of the
function implementations will end up in the final executable.
 
J

James Kanze

Pallav singh <[email protected]> wrote:

[...]
This is no different from regular template functions and inline
functions (which aren't inlined). In fact, template functions (and
membmer functions) are actually declared 'inline' implicitly, so they
work in the exact same way as regular inline functions.

No. Template functions are *not* implicitly declared inline
(unless they happen to be defined in a class template). Some
compilers may treat them the same, but the standard clearly
makes a difference.
 
J

Juha Nieminen

James Kanze said:
No. Template functions are *not* implicitly declared inline
(unless they happen to be defined in a class template). Some
compilers may treat them the same, but the standard clearly
makes a difference.

If they weren't, you would get linker errors when you use the same
template function in more than one compilation unit.

AFAIK they can't be implicitly declared 'static' either because then
any possible static variables inside the function would get duplicated
for each compilation unit where the function is called (which I think
would be against the specification of template functions).

(Of course here I'm talking about template function definitions. These
definitions get an implicit 'inline' declaration even without an explicit
'inline' keyword. Template function *declarations* are a different story,
of course, as "instantiating" them only instantiates a function declaration
rather than a function definition, in which case 'inline' wouldn't make
much sense.)
 
A

Alf P. Steinbach /Usenet

* Juha Nieminen, on 09.07.2010 13:47:
If they weren't, you would get linker errors when you use the same
template function in more than one compilation unit.

The linker behavior, discarding redundant linker records, is the same yes. But
the C++ concept of "inline" is different and has different rules, in particular
the machine code inlining hint of "inline". Just to invent a name for the common
linker behavior, let's talk about DISCARDABLE definitions.

Then one property of an "inline" routine is that it is DISCARDABLE, and so is an
instantiation of a routine template.

However, an explicit full specialization of a routine template is not
DISCARDABLE. And yes, you do get linker errors if you forget to smack an
"inline" on that! One might rationalize this by saying that it's no longer a
template but just an ordinary routine -- except that it does have enough
memory of its template origins, so to speak, that it can coexist with a really
ordinary routine of the same type and name:


<code>
#include <iostream>
using namespace std;

template< class Type >
void foo( Type const& )
{
cout << "General template" << endl;
}

template<> void foo( double const& )
{
cout << "Fully specialized template" << endl;
}

void foo( double const& )
{
cout << "Completely ordinary routine" << endl;
}

int main()
{
foo( 3.14 );
foo<double>( 3.14 );
}
</code>


OK, that was perhaps a digression.

But anyway, the DISCARDABLE property of template instantiations does not include
the inlining hinting the "inline" does, and so it is misleading to talk about
"inline" for template instantiations.

AFAIK they can't be implicitly declared 'static' either because then
any possible static variables inside the function would get duplicated
for each compilation unit where the function is called (which I think
would be against the specification of template functions).
Right.


(Of course here I'm talking about template function definitions. These
definitions get an implicit 'inline' declaration even without an explicit
'inline' keyword.

No, they don't.

Using the terminology invented above, instantiations of them are DISCARDABLE,
/like/ "inline" routines.

That's all.

Template function *declarations* are a different story,
of course, as "instantiating" them only instantiates a function declaration
rather than a function definition, in which case 'inline' wouldn't make
much sense.)

Unclear what you mean here.


Cheers & hth.,

- Alf
 
J

James Kanze

If they weren't, you would get linker errors when you use the
same template function in more than one compilation unit.

Where do you find anything like that in the language definition?

Depending on the compiler, template function instantiations
(because there's nothing to be generated until you instantiate
a template) will be treated differently. But there's no hint to
inline unless the function definition is within the class body
(generally to be avoided if you want to maintain the code) or
has been declared inline.
AFAIK they can't be implicitly declared 'static' either
because then any possible static variables inside the function
would get duplicated for each compilation unit where the
function is called (which I think would be against the
specification of template functions).

Functions are never implicitely declared static (and a template
always has external linkage). You can declare member functions
static, however, template or no:

struct Toto
{
template<typename T>
static void function(T param1, Toto* param2);
};
(Of course here I'm talking about template function definitions. These
definitions get an implicit 'inline' declaration even without an explicit
'inline' keyword.

No they don't. I don't know where you're getting that
information from.
Template function *declarations* are a different story, of
course, as "instantiating" them only instantiates a function
declaration rather than a function definition, in which case
'inline' wouldn't make much sense.)

Yes and no. Inline means that you must see a definition
before the end of the translation unit, at least if the function
is used. In the case of a template, this is not required,
neither by the standard nor by current implementations. (There
must be a definition in at least one translation unit where the
template is instantiated, but not all.)
 
J

James Kanze

* Juha Nieminen, on 09.07.2010 13:47:
The linker behavior, discarding redundant linker records, is
the same yes.

Maybe, maybe not. Not all compilers generate redundant
instantiations to begin with.

[...]

struct Toto
{
template<typename T>
static int f(T const&);
};

template<typename T>
int Toto::f(T const&)
{
static int i = 0;
return ++i;
}

Of course, inline functions have the same problem. The compiler
has to solve it: there may only be one instance of Toto::f::i
per instantiation, regardless of how many translation units
instantiate the function for a given type.
 
A

Alf P. Steinbach /Usenet

* James Kanze, on 09.07.2010 16:58:
Maybe, maybe not. Not all compilers generate redundant
instantiations to begin with.

So?

Same behavior, discarding records, only it seems that you know about a compiler
where it's done before linking; which compiler is that?

struct Toto
{
template<typename T>
static int f(T const&);
};

template<typename T>
int Toto::f(T const&)
{
static int i = 0;
return ++i;
}

So?

:)

Juha was referring to "static" as in "internal linkage", which your code is not
an example of.


Cheers & hth.,

- Alf
 
J

James Kanze

* James Kanze, on 09.07.2010 16:58:

Same behavior, discarding records, only it seems that you know
about a compiler where it's done before linking; which
compiler is that?

Not discarding records. Not bothering to redo work that's
already been done. It's pretty much standard practice outside
of the Windows world (since CFront did it), with the exception
of g++.
 
A

Alf P. Steinbach /Usenet

* James Kanze, on 12.07.2010 17:42:
Not discarding records. Not bothering to redo work that's
already been done. It's pretty much standard practice outside
of the Windows world (since CFront did it), with the exception
of g++.

Excuse me, but concretely which compiler are you talking about here?

A compiler that does not "generate redundant instantantiations to being with"
and so doesn't have to discard to linker record?


Cheers,

- Alf
 
I

Ian Collins

* James Kanze, on 12.07.2010 17:42:

Excuse me, but concretely which compiler are you talking about here?

A compiler that does not "generate redundant instantantiations to being
with" and so doesn't have to discard to linker record?

For one example Sun CC used to place compiled template instantiations in
a template repository (Green Hills did (still does?) something similar).
This idea originated from CFront.

The template repository was dropped by Sun CC several years ago because
access to the repository was a bottleneck in distributed builds.
 
J

James Kanze

* James Kanze, on 12.07.2010 17:42:
Excuse me, but concretely which compiler are you talking about
here?

The original reference implementation for templates: CFront.
Sun CC. The versions of C++ that I've used on HP/UX. (I don't
know what aCC does.)

Not to mention Visual Age, which used a completely different
compilation model.
A compiler that does not "generate redundant instantantiations
to being with" and so doesn't have to discard to linker
record?

That was the standard technology for a long time.
 
J

Juha Nieminen

James Kanze said:
Where do you find anything like that in the language definition?

Depending on the compiler, template function instantiations
(because there's nothing to be generated until you instantiate
a template) will be treated differently. But there's no hint to
inline unless the function definition is within the class body
(generally to be avoided if you want to maintain the code) or
has been declared inline.

I'm talking about their behavior with respect to linking.

If you had a regular function (eg.) in a header file, like:

void foo() { std::cout << "foo\n"; }

and then that header file would be included in more than one compilation
unit, you would get a linker error about the same function definition being
found more than once, causing a clash.

The language offers a solution to that problem, namely the 'inline'
keyword:

inline void foo() { std::cout << "foo\n"; }

Now even if the function would appear in more than one compilation unit
(and thus ending in more than one object file), it will not cause a linker
error because now the linker will merge all these foo() definitions into
one (usually by choosing one of them and discarding the rest, and make all
the code call that one definition).

If we have a template function in the header instead, for example:

template<typename T>
void foo(T v) { std::cout << v << "\n"; }

and then this would be called in more than one compilation unit (with the same
template type), one would think that the same problem happens: Now the same
foo() appears in more than one object file, potentially causing a linker
error, and hence one would need to write it like:

template<typename T>
inline void foo(T v) { std::cout << v << "\n"; }

However, the 'inline' keyword is not necessary in this case. The linker
will behave as if it was specified even if you don't explicitly do so, and
thus all the foo() instances (of the same template type) will be merged into
one by the linker.
 

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
474,146
Messages
2,570,831
Members
47,374
Latest member
anuragag27

Latest Threads

Top