Skip to main content
gamedev.net
🔒 Locked

C++ template

Started by nlbs 24 replies 3k views
Original Post
nlbs
nlbs
example.h
template <class X, class Y>
class Example{
	public:
    Example(X m, Y n);
    ~Example();
	public:
		X x;
		Y y;
};
example.cpp
template <class X, class Y>
Example<X, Y>::Example(X m, Y n): x(m), y(n){

}

template <class X, class Y>
Example<X, Y>::~Example(){

}
main()
int main(int argc, char *argv[]){
  Example<int, char> a(2, 'y');
  cout<<a.x<<"\t"<<a.y<<endl;

  return EXIT_SUCCESS;
}

Whats wrong with the above Code ?? Its giving me Compilation errors.
Spoonbender
Spoonbender
Which errors are you getting, and on which lines?

Edit:

Looks like the problem is that your template member functions aren't visible when the template gets instantiated.

You can't implement the constructor and destructor (or any other member function of a class template) in a separate .cpp file.
Simian Man
Simian Man
It compiles and runs fine for me. What errors are you getting?

<edit> Spoonbender is correct, put the definitions in your header file.
SiCrane
SiCrane
In the future you should post what your errors are, not just that you are getting errors.

Unless your compiler supports the export keyword, and I'm willing to bet that yours doesn't, then you can't put the definition of a template in a separate source file without explicit instantiation for specific types. Without explicit instantiation, the complete definition of the template needs to be available at point of instantiation, which means, in effect, that the definition needs to go into the header. (Or an inline file of some sort, etc.)
nlbs
nlbs
Sorry I forgot to post the error message.

These are the error message
undefined reference to `Example<int, char>::Example(int, char)'undefined reference to `Example<int, char>::~Example()'undefined reference to `Example<int, char>::~Example()'


I dont think(like) Its good to code them in the header file.

So Whats the solution if I want to keep them in the separate cpp file.

EDIT

I am using gcc and as far I know it supports export keyword.
SiCrane
SiCrane
I already told you your options: use explicit instantiation or use a compiler that supports the export keyword.
SiCrane
SiCrane
Quote:
Original post by nlbs
I am using gcc and as far I know it supports export keyword.

It doesn't.
nlbs
nlbs
Quote:
Original post by SiCrane
I already told you your options: use explicit instantiation or use a compiler that supports the export keyword.


Doesn't gcc support export keyword ?? EDIT: sorry already answered

Can you give some explanation about explicit instantiation ??
Simian Man
Simian Man
Quote:
Original post by nlbs
Can you give some explanation about explicit instantiation ??


Just include the definitions in the header file. This is how the C++ standard library does it; there is no other choice.
nlbs
nlbs
Quote:
Original post by Simian Man
Quote:
Original post by nlbs
Can you give some explanation about explicit instantiation ??


Just include the definitions in the header file. This is how the C++ standard library does it; there is no other choice.


Sorry I didn't understand correctly.
Hmm did you mean put the constructor in the header file ??
stonemetal
stonemetal
Throw a #include in the bottom of the header file that refers to the implementation file.
SiCrane
SiCrane
Quote:
Original post by nlbs
Can you give some explanation about explicit instantiation ??

Try throwing "explicit template instantiation" into your favorite search engine and see what you get.
nlbs
nlbs
Quote:
Original post by stonemetal
Throw a #include in the bottom of the header file that refers to the implementation file.


I added
#include "example.cpp"
at the end of example.h

and it gave me teh following error

example.cpp:23: error: redefinition of ‘Example<X, Y>::Example(X, Y)’example.cpp:23: error: ‘Example<X, Y>::Example(X, Y)’ previously declared hereexample.cpp:28: error: redefinition of ‘Example<X, Y>::~Example()’example.cpp:28: error: ‘Example<X, Y>::~Example()’ previously declared here
Simian Man
Simian Man
Quote:
Original post by stonemetal
Throw a #include in the bottom of the header file that refers to the implementation file.


That approach will work, but it is essentially the same as only using a header file, and abuses the header/source file construct and confuses people. I'd recommend putting template all definitions in headers:

example.h
template <class X, class Y>class Example{	public:    Example(X m, Y n);    ~Example();	public:		X x;		Y y;};template <class X, class Y>Example<X, Y>::Example(X m, Y n): x(m), y(n){}template <class X, class Y>Example<X, Y>::~Example(){}


main.cpp
int main(int argc, char *argv[]){  Example<int, char> a(2, 'y');  cout<<a.x<<"\t"<<a.y<<endl;  return EXIT_SUCCESS;}
nlbs
nlbs
Do I need to put all member functions in the header file or only put the constructor and destructor in the header.
popsoftheyear
popsoftheyear
Due to the nature of templates, they typically require that you put the definition in the header file (as many have already said). Not just the constructor.. all members. Templates shouldn't have any related .cpp files. If you feel you MUST keep things separated, put the definition in an .hpp file and include that at the end of your template's .h file, like you sort of already did... just not with .cpp.

There are some compilers that let you circumvent this and put the definition in the .cpp file, but that is actually unusual, and the compiler has to do extra work to make it happen anyway. The whole reason you can do so many tricks with templates is BECAUSE the definitions are in the header... seriously it's not bad coding or anything, it's a requirement. Note that when it comes to other classes, than yes, put the definition in the .cpp just like you think is good (or like) to do. This is also typical (unless it's an inline function, etc. etc... like anything else in C++ there are exceptions and exceptions to the exceptions)

Cheers
-Scott
Spoonbender
Spoonbender
Quote:
Original post by nlbs
Do I need to put all member functions in the header file or only put the constructor and destructor in the header.


Everything that depends on a template argument must have a definition visible when used. This goes for constructor/destructor in a template class, as well as other members, template functions and anything else. In short, yes, everything should be in the header.

The clue really is in the name, "template". A class template is not a class, it's a template for creating classes. And if I can't see the template, I can't use it to generate classes. Keep that in mind, and this requirement makes a lot more sense.
nlbs
nlbs
Thanks for all your answers

Does C++ STL uses .hpp extension or this technique ??
if not which technique it uses ??
Antheus
Antheus
Quote:
Does C++ STL uses .hpp extension or this technique ??

It uses the following approach (so do I):
template <class X, class Y>class Example{public:    Example(X m, Y n)      : x(m)      , y(n)    {      // body    }    ~Example()    {      // body    }private:  X x;  Y y;};


Given universal absence of export keyword, I never saw any particular use for declaring functions externally, except leading to a lot of clutter for absolutely no real benefit.

Just do it like C#/Java classes look like - put definition together with declaration.

Separating the both doesn't save any compilation time and makes maintenance more difficult. I cannot remember any issues that would arise from doing so.
nlbs
nlbs
Thanks for the information about STL.

Quote:
Original post by Antheus
....
Separating the both doesn't save any compilation time and makes maintenance more difficult. I cannot remember any issues that would arise from doing so.
I disagree.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.