Sign in to follow this  
nlbs

C++ template

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ??

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ??

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 here
example.cpp:28: error: redefinition of ‘Example<X, Y>::~Example()’
example.cpp:28: error: ‘Example<X, Y>::~Example()’ previously declared here

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
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.
You are of course welcome to disagree, but think about what happens if you change the return type or parameter list of a function in the header file, and forget to change it in the .cpp file...

Quote:
Original post by Bregma
Quote:
Original post by popsoftheyear
In case 1 you only have to change things in 1 place, in case 2 you have to change them in 2 places.
In the case of the standard library, however, the interface changes only once every 5 to 10 years, but the implementation can be messy. Making class declarations as readable as possible (under the constraints of name uglification) in the standard library headers means separating the member functin implementations into separate chunks of code.
libstdc++ seems to use the extension '.tcc' to name header files containing template implementation separately from the template declaration.

[Edited by - swiftcoder on October 10, 2008 1:03:40 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by popsoftheyear
In case 1 you only have to change things in 1 place, in case 2 you have to change them in 2 places.


In the case of the standard library, however, the interface changes only once every 5 to 10 years, but the implementation can be messy. Making class declarations as readable as possible (under the constraints of name uglification) in the standard library headers means separating the member functin implementations into separate chunks of code.

That's the reasoning behind separating declarations and definitions in some standard library implementations. It's not for any technical reason but to help clarify the interface for those brave souls who choose to use the source as documentation.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
think about what happens if you change the return type or parameter list of a function in the header file, and forget to change it in the .cpp file...
Your IDE, assuming it is a good IDE, does it for you.

Share this post


Link to post
Share on other sites
Quote:
Original post by Bregma

That's the reasoning behind separating declarations and definitions in some standard library implementations. It's not for any technical reason but to help clarify the interface for those brave souls who choose to use the source as documentation.


Surprisingly, this is never a complaint in C#, Java or Python or many other languages which do not separate interface from implementation.

At very least, I've never seen it as major argument, nor is anyone too anxious to follow this practice. And a major reason for this separation is purely technical.

Quote:
Your IDE, assuming it is a good IDE, does it for you


And my IDE can collapse code blocks, so clutter is not a problem. It can even work selectively on comments, scope or function level, and perhaps a few more.

However the same IDE does not know how to refactor complex template declarations. Or anything else for that matter, the most is text-based find/replace.

Normalization applies to more than just databases, and while with non-templated classes argument of build times is valid, in case of templates it's not.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this