Click to See Complete Forum and Search --> : Explicit template instanciation


Martin Boucher
September 24th, 2002, 08:35 AM
Hi,

In "C++ programming Language" from Bjarne Stroustrup, it is told that it's possible to instanciate (explicitly) a class template, a function template or just a member of a class template. I want to instanciate a function template of a class that is not a template itself. So, that case isn't covered in the book. I try few things as :


// My class that is not a template (in .h file) :
class CVar
{
...
template< typename T >
T* ValueGetToken( T* buf_, int buflen_ ) const;
...
};

// Explicit instanciation (in .cpp file) :
template char* CVar::ValueGetToken( char*, int ) const;


I'm always having the same linking problem. So my function isn't instanciate. Is it possible to do this? I'm compiling with Visual C++ 6 (I know it's not the reference for working with templates but I have no choice since it's the compiler my company uses).

thanks,
Martin

Yves M
September 24th, 2002, 08:51 AM
Hi,

First of all, I'm not an expert in templates (yet), so I'm not sure whether this will help you. But you can use overloading instead of explicit template instantiation.


T* ValueGetToken( T* buf_, int buflen_ ) const;

char* ValueGetToken( char* buf_, int buflen_) const;

proxima centaur
September 24th, 2002, 09:06 AM
I don't know what the problem is, but here's how I do things:


class CVar
{
template< typename T >
T* ValueGetToken( T* buf_, int buflen_ ) const;

char *
ValueGetToken( char * yo, int ya ) const;
};

template <typename T>
T*
CVar::ValueGetToken( T* yo, int ya ) const
{
T* toto;

return toto;
}

char *
CVar::ValueGetToken( char * yo, int ya ) const
{
char * toto;

return toto;
}


Hope this helps.

Bonne chance! (moi aussi je suis débutant avec les templates! ;) )

Yves M
September 24th, 2002, 09:22 AM
Well, proxima, you're doing exactly what I suggested in my post ;)

Overloading a function instead of template instantiation...

I wonder why none of our resident gurus have replied to this post yet ;)

Graham
September 24th, 2002, 09:33 AM
First thing to note is that the instantiation given is (I think) wrong. I'm not that up on templates (especially template member functions), but I think the explicit instantiation should be:

char* CVar::ValueGetToken<char>( char*, int ) const

not

template char* CVar::ValueGetToken( char*, int ) const

which I think is syntactically incorrect. I also doubt if you could put it in the cpp file without "export".

Also, I think that this sort of thing may be a non-starter with VC++6 anyway - its template handling is seriously broken around template member functions.

proxima centaur
September 24th, 2002, 09:33 AM
I guess we were typing the same thing at the exact same time, only you hit the send button just a few minutes before me! eheh

Yeah... will the real guru please stand up? please stand up? :D

proxima centaur
September 24th, 2002, 09:37 AM
Just an "aparté" Martin, just be careful with templates and VC++ 6.0. Template support is crappy in this version of VC. Some behaviour is NOT the intended one. I suggest you try .NET. It has resolved most of the issues we had with both STL and templates.

Yves M
September 24th, 2002, 09:54 AM
Right, that's probably it, Graham.

The method that works is :
class CVar
{
public:
template< typename T >
T* ValueGetToken( T* buf_, int buflen_ ) const
{
}

char* ValueGetToken<char>( char* buf_, int buflen_) const;
};

char* CVar::ValueGetToken( char* buf_, int buflen_) const
{
printf("char *\n");
return buf_;
}


I wonder though why you don't have to specify in the implementation of ValueToken that it's a template specialization ? I mean something like
char* CVar::ValueGetToken<char>( char* buf_, int buflen_) const
would seem more logical...

proxima centaur
September 24th, 2002, 10:01 AM
I've talked to the office guru and here's another solution:


template <>
char *
CVar::ValueGetToken( char * yo, int ya ) const
{
char * toto;

return toto;
}


Of course, the difference in the syntax is very slight, but the difference in the meaning is great.

This is template specialization, whereas the former one was method overload.

A method overload has precedence over template generated methods, thus this is a subtle difference but one that could lead to erroneous results.

As to why template <> and not just template, we don't know. It might be "Microsoft specific".

proxima centaur
September 24th, 2002, 10:03 AM
Originally posted by Yves M
I wonder though why you don't have to specify in the implementation of ValueToken that it's a template specialization ? I mean something like
char* CVar::ValueGetToken<char>( char* buf_, int buflen_) const
would seem more logical...

Why would you need to specify the type when it is already specified in the parameter list? The compilor already knows that when it deals with char* it needs to call this method. It would be over defining the method by using redundant information.

Graham
September 24th, 2002, 10:44 AM
I need to do some more reading about this, cos I'm getting to the limits of my knowledge in this area. There is a fairly major difference between template functions and template classes. Now this is where my brain starts hurting, but I remember seeing somewhere something about not using the "template<>" bit at the start of a function explicit specialisation (you do use it when explicitly specialising a class).

Ach, I need to lie down in a dark room for a while. I'll do some looking up and see if I can come up with the definitive answer (which will probably include the words "except in VC++6").

Graham
September 24th, 2002, 10:52 AM
According to Saint Bjarne, it looks like the simplest explicit specialisation would be:

template <> char * CVar::ValueGetToken(char* pc, int i) const

My memory must be going........

what was I saying?

proxima centaur
September 24th, 2002, 10:57 AM
Thanks for owning and actually reading Bjarnes' book Graham! :D

Yves M
September 24th, 2002, 11:26 AM
I'll finally get it delivered this week :D

Martin Boucher
September 24th, 2002, 01:19 PM
Thanks for all the answers but it doesn't help. Listen! MSDN has something to tell : Linking error 2001 (http://msdn.microsoft.com/library/en-us/vccore/html/LNK2001.asp) Look for the first Coding Problem. This is the answer.

For those who has answer something, let's clarify some concepts related to templates.

First, if I use a template instead of overloading, it's because I want to avoid code duplication. Template exits only for that. Saying something just one time no matter the type of an object. So instead of :


template< typename T >
T* ValueGetToken( T* buf_, int buflen_ ) const;


I could use :


char* ValueGetToken( char* buf_, int buflen_ ) const;
wchar_t* ValueGetToken( wchar_t* buf_, int buflen_ ) const;


But it's exactly what I have and what I want to replace whit my template method. Just to avoid code duplication because both methods have the same code.

Second, someone was septical about my notation :


template char* CVar::ValueGetToken( char*, int ) const;


I'm not really sure of this one because I haven't found them in Bjarne's book. But those following are legal (see Bjarne's book (3e edition) section C.13.10 p.866) :


template class vector<int>; // explicit instantiation of a class
template int& vector<int>::operator[](int); // explicit instantiation of a class member
template int convert<int,double>(double); // explicit instantiation of a function


The 3rd one is the closest of what I try. I have a method template of a class (not a template class).

Also, there is a difference between specialization and explicit instantiation.

When you write code as :


template<> char* ValueTokenGet( char*, int );


You are writing a specialization of ValueTokenGet for the type char. So the definition of the function would not be used for the type char, the specialization would be used.

Explicit instantiation of a template lets you ensure that the template is define somewhere for a type T. The major advantage that I saw in this feature is that you can define the body of a function in a .cpp file. Not in the .h file. That's remove many include from the .h file (hence reducing the dependencies between files).

Martin

proxima centaur
September 24th, 2002, 02:59 PM
Well, Martin, you seem to know how templates work.

But what exactly is your question then? :rolleyes:

As I fail to understand what is the problem.

Either you want to have a template (or function template) that is totally generic whatever the type or you specialize some of the types to do specific stuff depending on the type. It's simple.

But what are you trying to do?!

Martin Boucher
September 24th, 2002, 05:27 PM
Yes I begin to well understand templates. Compiling templates with Micro$oft is the better thing to learn.

So, my question was : How can I explicitly instantiate a template function member of a class (that class not being itself a template)?

I know (from Bjarne's book) that I can explicitly instantiate a class template :

template class vector<int>;

or I can explicitly instantiate a member of a class template :

template int& vector<int>::operator[](int);

or I can explicitly instantiate a function template :

template int convert<int,double>(double);

But I never saw an example of my problem.

What I'm trying to do? Having a function member that works for char and wchar_t without duplicating code (no function overload) nor defining my template function member in my class definition. With templates, too many other header files are required. That leads to software that always recompile everything. The solution is explicit instanciation.

Here is how I solve my problem. I use function overloading in my class definition (declaring 2 method ValueTokenGet one for char and the other for wchar_t). But the implementation of both function just call a function template. So the code is reused for both char types and everything is implemented in my .cpp file. No more header files in my .h file.

Martin

proxima centaur
September 24th, 2002, 07:42 PM
Ahhh....
I now "feel" your problem...

Let me think ;)

why don't you put the code for both char and wchar in the generic method?


template <typename T>
T*
CVar::ValueGetToken( T* yo, int ya ) const
{
T* toto;

return toto;
}


This way, any type coming through this method is using the same code, avoiding code duplication.

I see, this will lead to recompiling every time you make a change :rolleyes:

Well, sorry Martin, I tried, but I can't find a better solution than the one you already found :(

Good luck!

Graham
September 25th, 2002, 04:06 AM
OK. I get the picture now (it's section C.13.10 of Saint Bjarne's book).

I suspect that this is one of those VC++ things - it just can't handle it.

Amn
September 26th, 2002, 05:13 AM
Originally posted by Graham
According to Saint Bjarne, it looks like the simplest explicit specialisation would be:

template <> char * CVar::ValueGetToken(char* pc, int i) const

My memory must be going........

what was I saying?

Get down to Earth folks ;) YOu forgot we are dealing with the "mighty" M$soft compiler here.... it wont do any of the "template <>" tricks, regardless if Bjarne comes appears the thin air before them and writes it down with golden paint on the wall ;) *hint* *hint* *give us ANSI c++*