tags:

views:

257

answers:

2

Hi guys, After few weeks brake (had to finish couple of assignments for my study, by the way, why God allowed anyone to invent Java?), I'm trying to expand and extend my knowlege of templates with book: Templates - The Complete Guide by David Vandevoorde and Nicolai M. Josuttis, and what I'm trying to understand at this moment is as in topic, explicit instantiation of templates. I mean I don't have a problem with the mechanism as such but I can't imagine a situation in which I would like or want to use this feature. If anyone can explain that to me I will be more than grateful. Thank you.

+3  A: 

Directly copied from http://msdn.microsoft.com/en-us/library/by56e477%28VS.80%29.aspx:

Explicit instantiation lets you create an instantiation of a templated class or function without actually using it in your code. Because this is useful when you are creating library (.lib) files that use templates for distribution, uninstantiated template definitions are not put into object (.obj) files.

(For instance, libstdc++ contains the explicit instantiation of std::basic_string<char,char_traits<char>,allocator<char> > (which is std::string) so every time you use functions of std::string, the same function code doesn't need to be copied to objects. The compiler only need to refer (link) those to libstdc++.)

KennyTM
Yup, the MSVC CRT libraries have explicit instantiations for all the stream, locale and string classes, specialized for char and wchar_t. The resulting .lib is over 5 megabytes.
Hans Passant
How does the compiler know that the template has been explicitly instantiated elsewhere? Isn't it going to just generate the class definition because it's available?
@STing: If the template is instantiated, there will be an entry of those functions in the symbol table.
KennyTM
@Kenny: You mean if it's already instantiated in the same TU? I would assume any compiler is smart enough not to instantiate the same specialization more than once in the same TU. I thought the benefit of explicit instantiation (with regards to build/link times) is that if a specialization is (explicitly) instantiated in one TU, it will not be instantiated in the other TUs in which it is used. No?
@STing: Yes. __
KennyTM
@Kenny: So we come full circle to my *original* question. "How does the compiler know that the template has been explicitly instantiated elsewhere?" ????
@STing: I mean "in the same TU". If the compiler supports precompiled headers then the same instantiation may be reused. But in general each template will be repeated instantiated for each TU. The instantiation leads to an entry in the symbol table which can be removed on duplication. See http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html#Template-Instantiation for how GCC handles this.
KennyTM
@Kenny: I know about the GCC option to prevent implicit instantiation, but this is not a standard. As far as I know VC++ has no such option. Explicit inst. is always touted as improving compile/link times (even by Bjarne), but in order for it to serve that purpose, the compiler must somehow know to not implicitly instantiate templates (e.g., via the GCC flag), or must not be given the template definition, only a declaration. Does this sound correct? I'm just trying to understand why one would use explicit instantiation (other than to limit the concrete types).
Precompiled headers aren't going to prevent instantiation, unless the instantiation occurs in a header, perhaps...
A: 

If you define a template class that you only whant to work for a couple of explicit types.

Put the template declaration in the header file just like a normal class.

Put the template definition in a source file just like a normal class.
Then at the end of the source file explicitly instanciate only the version you want to be available.

Silly example:

// StringAdapt.h
template<typename T>
class StringAdapter
{
     public:
         StringAdapter(T* data);
         void doAdapterStuff();
     private:
         std::basic_string<T> m_data;
};
typedef StringAdapter<char>    StrAdapter;
typedef StringAdapter<wchar_t> WStrAdapter;

Source:

// StringAdapt.cpp
#include "StringAdapter.h"

template<typename T>
StringAdapter<T>::StringAdapter(T* data)
    :m_data(data)
{}

template<typename T>
void StringAdapter<T>::doAdapterStuff()
{
    /* Manipulate a string */
}

// Explicitly instanciate only the classes you want to be defined.
// In this case I only want the template to work with characters but
// I want to support both char and wchar_t with the same code.
template class StringAdapter<char>;
template class StringAdapter<wchar_t>;

Main

#include "StringAdapter.h"

// Note: Main can not see the definition of the template from here (just the declaration)
//       So it relies on the explicit instanciation to make sure it links.
int main()
{
  StrAdapter  x("hi There");
  x.doAdapterStuff();
}
Martin York
Is it correct to say that if the compiler has the entire template definition (including function definitions) in a given translation unit, it *will* instantiate a specialization of the template when needed (regardless of whether that specialization has been *explicitly* instantiated in another TU)? I.e, in order to reap the compile/link-time benefits of explicit instantiation, one must only include the template *declaration* so that the compiler *cannot* instantiate it?