help-gplusplus
[Top][All Lists]
Advanced

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

Re: Template instantiation in libraries


From: Guy Harrison
Subject: Re: Template instantiation in libraries
Date: Sat, 11 Dec 2004 01:00:14 GMT
User-agent: KNode/0.7.7

John Max Skaller wrote:

> 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.

Hmm, possibly. Good write up, mind.

> 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.

Obviously has to happen with static lib.

> 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.

Or even basic_string<TCHAR>

> 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.

My preference is to declare (even templates) *.hpp (template bodies in
*.cci) and instantiations *.cpp (along with rest of code).

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

Older BCB variants are a bit of a bugger!

The rest of your writeup seems reasonable...

> 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.
> rr
> 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]