2

Technique 1 -> Results in error

I have three files MyType.h, MyType.cpp & main.cpp

MyType.h

#ifndef MYTYPE_H
#define MYTYPE_H

#include<iostream>
using namespace std;

template <class T,int iMax>

class A{
    T iData;
public:
    void vSetData(T iPar1);
    void vDisplayData();
};
#endif

MyType.cpp

#include"MyType.h"

void A::vSetData(T iPar1){
    if(iPar1 <= iMax)
        iData = iPar1;
}
void A::vDisplayData(){
    cout<<"\nData is: "<<iData<<endl;
}

main.cpp

#include"MyType.h"

typedef A<int,20> MyType;

int main(){
    int x = 12;
    MyType obj;
    obj.vSetData(12);
    obj.vDisplayData();
    return 0;
}

ERRORS: 10 errors. They are as follows:-

  • mytype.cpp(2) : error C2955: 'A' : use of class template requires template argument list
  • mytype.h(9) : see declaration of 'A'
  • mytype.cpp(2) : error C2955: 'A' : use of class template requires template argument list
  • mytype.h(9) : see declaration of 'A'
  • mytype.cpp(2) : error C2065: 'T' : undeclared identifier
  • mytype.cpp(2) : error C2146: syntax error : missing ')' before identifier 'iPar1'
  • mytype.cpp(2) : error C2761: 'void A::vSetData(T)' : member function redeclaration not allowed
  • mytype.cpp(2) : error C2059: syntax error : ')'
  • mytype.cpp(2) : error C2143: syntax error : missing ';' before '{'
  • mytype.cpp(2) : error C2447: '{' : missing function header (old-style formal list?)
  • mytype.cpp(6) : error C2955: 'A' : use of class template requires template argument list
  • mytype.h(9) : see declaration of 'A'
  • mytype.cpp(6) : error C2509: 'vDisplayData' : member function not declared in 'A'
  • mytype.h(9) : see declaration of 'A

Technique 2 -> Works fine.

AboveCodeInOneFile.cpp

#include<iostream>
using namespace std;

template <class T,int iMax>

class A{
    T iData;
public:
    void vSetData(T iPar1){
        if(iPar1 <= iMax)
            iData = iPar1;
    }
    void vDisplayData(){
        cout<<"\nData is: "<<iData<<endl;
    }
};

typedef A<int,20> MyType;

int main(){
    int x = 12;
    MyType obj;
    obj.vSetData(12);
    obj.vDisplayData();
    return 0;
}

Please let me know what mistake i am doing in Technique 1

Abhineet
  • 6,459
  • 10
  • 35
  • 53
  • You're not getting errors while executing. You're getting compilation errors. – R. Martinho Fernandes Jul 19 '11 at 12:02
  • Yes I am getting compile time error. – Abhineet Jul 19 '11 at 12:03
  • possible duplicate of [Why should the implementation and the declaration of a template class be in the same header file?](http://stackoverflow.com/questions/3749099/why-should-the-implementation-and-the-declaration-of-a-template-class-be-in-the-s) – pmr Jul 19 '11 at 12:16
  • 1
    @pmr - That is not what is asked here, but the next question once it compiles. :-) – Bo Persson Jul 19 '11 at 12:35
  • @Bo You are right. My "*.cpp + template" == duplicate reflexes got ahead of me. – pmr Jul 19 '11 at 12:47

5 Answers5

3

When defining a template class, the method definition must be seen by the compiler. So they have to be in the header file.

Edit

You have to include the method implementation, so it's seen by the compiler. You can do it by including them from another `MyType_impl.h" file:

template <class T, int iMax>
void A<T, iMax>::vDisplayData()
{
  cout<<"\nData is: "<<iData<<endl;
}
René Richter
  • 3,839
  • 3
  • 34
  • 42
2

Technique 1 is wrong for templates. Don't use it.

Think of templates as blueprints for actual functions. Blueprints by themselves are not compilable. Only when you substitute template arguments (<class T,int iMax>) the actual functions are built. Because of this the compiler must see the blueprints when it tries to build functions from templates. In order to see the blueprints they must reside completely in header files.

Dialecticus
  • 16,400
  • 7
  • 43
  • 103
2

Each method definition needs the full class name decoration above it:

template <typename T>
void A<T>::vSetData(T iPar1){
    if(iPar1 <= iMax)
        iData = iPar1;
}

template <typename T>
void A<T>::vDisplayData(){
    cout<<"\nData is: "<<iData<<endl;
}

When you do this however you'll get other compile errors, for the reasons Abhineet outlined. To fix this, you could put the definitions I wrote into the header file, beneath the class declaration, or you could put it in another header (MyType_Inc.h) and include /that/ header in the class declaration header

Cechner
  • 849
  • 7
  • 19
1

When you define the member functions, you have to repeat the template parameters

template <class T,int iMax>
void A<T, iMax>::vSetData(T iPar1)
{
     if(iPar1 <= iMax)
         iData = iPar1; 
} 

That saves you from the compile errors.

The next problem is that templates defined in a .cpp file can only be used in that file. If you want to use them somewhere else, you really should put the definitions in the header.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
1

There are two problems with your first version.

When implementing a member of a class template outside the class, you need to declare it as a template:

template <class T,int iMax>
void A<T,iMax>::vSetData(T iPar1){
    if(iPar1 <= iMax)
        iData = iPar1;
}

Also, the function definitions need to be available in any compilation unit that instantiates the template. In practice, this means you should usually define them inline (either inside the class template definition, or outside it but in a header file and declared inline). Simply defining them in a source file like you do will cause link errors.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644