help-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Template instantiation in libraries


From: John Max Skaller
Subject: Re: Template instantiation in libraries
Date: Tue, 07 Dec 2004 03:07:32 +1100
User-agent: Pan/0.13.3 (That cat's something I can't explain)

On Sat, 04 Dec 2004 09:01:29 +0000, Guy Harrison wrote:

>>Ex, I'm
>> expanding much of the code for std::basic_string<char> (also known as
>> std::string) because it is commonly used.
>> 
>> Unfortunately, even when the required code is placed in the library, the
>> compiler/linker defaults to creating an instantiated copy of the template
>> code in the executable as a weak symbol.
> 
> Never looked myself (as I've never had your problem)...
> 
> template <> //foo
> 
> ..against a static lib works fine. 

Hmmm. This isn't right. Perhaps simplifying the actual
standard template, this code:

template <> basic_string<char>;

is NOT an instantiation. It merely declares a specialisation
for the type argument charT = char. This means you are
**required** to actually define it somewhere if you use it.
See 14.7.1.

This is not what you want at all. You do not want a special version
of the template basic_string for type char, what you want
is the *usual* template. 

This is done like this:

template basic_string<char>;

Notice no <> after the word 'template'.
This is called an explicit instantiation.
[Note: no defaults -- you have to supply all the arguments]
See 14.7.2.

To build a library of instantiations, you just make a
library.cpp file and put some explicit instantiations in it.

Does this mean your compiler will not instantiate
the template in another compilation?

No, it doesn't mean that. This is compiler dependent.
The old Cfront used to use a repository, and delay instantiation
until link time. Repositories are fast but messy, and there
is no choice if you have an old linker without initialised
common blocks.

However GNU ld does have initialised common blocks, so g++ can
instantiate the template in every translation unit that 
needs an instantiation, and merge them at link time.

Including with your prebuilt library.

So can you use an explicit specialisation to stop that
gratuitous instantiation in each translation unit?

NO! Not if you want a well defined program.
It is explicitly prohibited!
See 14.7.3/6.

So basically, what Guy said may well work with some
versions of g++, but it isn't portable,
and indeed I'd consider it a bug -- although there
is no requirement for a diagnostic, a quality
implementation should provide one.

The reason g++ doesn't is almost certainly a weak
name mangling scheme: an instantiation of a template
should never have the same name as an
instantiation of a specialisation. This 'fault' probably
exists because of the HUGE cost of correctly encoding
specialisations (especially for functions..).

Anyhow, the explicit template instantiation

template thingamy<...>

was created precisely for your needs, although,
in the context of the older 'repository' based
instantiators, which only instantiated once:
the explicit instantiation then, once created,
meant that instantiation never need be done again
(as long as you linked it into the program).

On modern systems with dynamic linkage, it also
has an important use, since it allows you to control
whether a particular object (mainline or shared library)
contains an instantiation. This can be important to save
space and also prevent two versions existing (but of course
this is all beyond the scope of the Standard).

For an embedded system you might consider doing this:

(a) #include the whole template definition into 
a library file and use explicit instantiations
for the type arguments you want.

(b) Somehow cheat and make a header file
for the templates which does NOT contain any body.

(c) if you compile some code with these headers and
link against the library and you will get unresolved
externals for instantiations other than the ones
in your library.

You can then decide whether to extend the library
or rewrite the program to avoid using that template
instance.

Of course, using 'cheat' headers like that isn't
going to lead to well defined behaviour.. so for a
production build you should use the full headers,
and drop your library from the link (and check the
executable size is the what you expected).




reply via email to

[Prev in Thread] Current Thread [Next in Thread]