Problem with templates in C++

Started by
4 comments, last by xg0blin 19 years, 9 months ago
Hi, i don't understand what is the problem in the following C++ code. I am getting the error from compiler TempStack error LNK2019: unresolved external symbol "public: bool __thiscall CStack<int>::Pop(int &)" (?Pop@?$CStack@H@@QAE_NAAH@Z) referenced in function _main TempStack error LNK2019: unresolved external symbol "public: bool __thiscall CStack<int>::Push(int const &)" (?Push@?$CStack@H@@QAE_NABH@Z) referenced in function _main TempStack error LNK2019: unresolved external symbol "public: __thiscall CStack<int>::CStack<int>(int)" (??0?$CStack@H@@QAE@H@Z) referenced in function _main TempStack fatal error LNK1120: 3 unresolved externals i have compiled the following code with empty main() but when i instantiate the object of the class in main() i am getting the error shown above. I m unable to understand this error, please help me, the code is as follows /*** Header file for class declaration ***/ #ifndef Stack_h #define Stack_h template<class T> class CStack { private: T *stk; int size; int top; public: CStack(int = 10); ~CStack() { delete[] stk; } bool Push(const T&); bool Pop(T&); bool isFull(void); bool isEmpty(void); }; #endif /*** cpp file for definition of class member functions ***/ #include"Stack.h" template<class T> CStack<T>::CStack(int size) { this->size = size; top = -1; stk = new T[this->size]; } template<class T> bool CStack<T>::isFull(void) { return(Top==size-1); } template<class T> bool CStack<T>::isEmpty(void) { return(Top==-1); } template<class T> bool CStack<T>::Push(const T &value) { if(!isFull()) { stk[++top] = value; return true; } else { return false; } } template<class T> bool CStack<T>::Pop(T &RetVal) { if(!isEmpty()) { RetVal = stk[top]; top--; return true; } else { return false; } } /*** main ***/ #include<iostream> #include"Stack.h" using namespace std; void main(void) { CStack<int> st1(3); int value; st1.Push(1); st1.Push(2); st1.Push(3); st1.Pop(value); cout<<value<<"\n"; st1.Pop(value); cout<<value<<"\n"; st1.Pop(value); cout<<value<<"\n"; } please tell me what am i doing wrong here. thanx a lot, bye.
Advertisement
Put the functions that are in the cpp file in the header file below the class definition. It is basically a side effect of how the compiler generates the code for template instantiations.
In your header file, at the very bottom, put

#incude "WhateverYouNamedYourTemplateClassFile.template"

Note that it is a .template file and not a .cpp file, so you'll need to save it as WhateverYouNamedYourTemplateClassFile.template rather than WhateverYouNamedYourTemplateClassFile.cpp. That's the way I normally do it. The other route is to include your implementation in your header file.
Quote:http://www.codeguru.com/Cpp/COM-Tech/atl/tutorials/article.php/c3617/

Template Compilation Models
When writing template classes, function definitions are usually stored in a header file along with their declarations, and not in a separate .cpp file. Trying to do otherwise typically will result in a linker error. This is because most compilers require template definitions to be available to each translation unit that uses them, through the inclusion of header files.

The reason for this behaviour is that templates are only a pattern, and as such they do not directly produce code until the compiler comes a across an instantiation. If we create a CCalculator<int> instance, and invoke one of its class methods, the compiler will need to have the function definition at hand. If the header file is included and contains this definition, all is well. But if the definition resides in a .cpp file, the compiler cannot be expected to find the pattern at the time, and use it to generate the required code. However, the C++ standard does provide a mechanism to aid compilers. The export keyword instructs the compiler that we are providing a separately compiled template:

// In MyTemplateFunction.h
template<class T>
void myTemplateFunction(const T &t1);

// In MyTemplateFunction.cpp
export template <class T>
void myTemplateFunction(const T &t1)
{
...
}

Today, most compilers require template definitions to be explicitly added to a translation unit through header file inclusion, although the standard does cater to definitions that reside in .cpp files. The two different template compilation models are traditionally known as the inclusion model and the separation model. At the time of writing, the only compiler that I know of which supports the separation model is the Comeau C++ compiler. The Comeau implementation goes some way to support the usage of the export keyword as intended by the standard, but is currently still in beta release.

Hi,

Tnanx alot, it worked, but i didn't get it. Why is this that defining members of a template class in .cpp file does not work. Is it something to do with the way compiler compiles the template code. Please tell me what exactly is the reason for this.i m curious.

thanx again
bye.
Quote:Original post by Buzz1982
Hi,

Tnanx alot, it worked, but i didn't get it. Why is this that defining members of a template class in .cpp file does not work. Is it something to do with the way compiler compiles the template code. Please tell me what exactly is the reason for this.i m curious.

thanx again
bye.


I agree that it is stupid that it is designed that way, because you want to keep your implementation hidden, but I suppose it's a necessary evil for now. It's because the compiler has to automatically generate code on the fly when compiling, and if all you give it is the header and not the definition, it doesn't know what to do for lack of a definition before linking, and thus can't generate the code. Anyways, that's why you have to include the definition in the header file. I wish they'd come up with a better way to handle it, but oh well.

This topic is closed to new replies.

Advertisement