3

Possible Duplicate:
Why should the implementation and the declaration of a template class be in the same header file?

I am trying to define a template in a header file and the definition of it in a cpp file and the template should be defined within a derived class. So this is what I got:

Header file:

#ifndef  ........
#define .....
 template <class mytypename>
 class abcBaseClass:public abcDerivedClass{
 public:
     mytypename getvalue(char*)
};
#endif


Source file:

mytypename abcDerivedClass<mytypename>::getvalue(char* name){

}

I just wanted to know if this is the correct way of doing it?.

This is what I am trying to achieve... The final way I want to make the call is

double x = a->getvalue<double>(char)
Community
  • 1
  • 1
vadugs
  • 71
  • 1
  • 4
  • The implementation must end up in the same file as the declaration unless you explicitly instantiate the types. Also `typename` is a reserved word. – Seth Carnegie Oct 18 '12 at 18:00
  • The correct way is to put the entire template definition in the header. – Kerrek SB Oct 18 '12 at 18:00
  • What are you really trying to do? `typename` is not a valid name for the template arguments, and in that code `base` inherits from `derived` which is at the very least a counter-intuitive choice of names. – David Rodríguez - dribeas Oct 18 '12 at 18:03
  • Mybad... Ignore the typename... And THANK YOU everyone for notifying me that... I just changed it to mytypename... Other than that ... I just wanted to know if I am correct... I just want my template definition and declaration to be on separate files – vadugs Oct 18 '12 at 18:10
  • @vadugs, read my answer for the work-around (with some flaws). Also, Mark's answer provides another work-around, requiring a bit of extra work though. – Jimmy Lu Oct 18 '12 at 18:26

3 Answers3

3

Similar questions have been asked many times on SO already.

But anyways...

First of all, you made some syntax errors.

Instead of

#ifndef  ........
#define .....
 template <class typename>
 class abcBaseClass:public abcDerivedClass{
 public:
     typename getvalue(char*);
};
#endif

it should be something like this.

#ifndef  ........
#define .....
 template <typename T>
 class abcBaseClass:public abcDerivedClass{
 public:
     T getvalue(char*);
};
// Definition follow in this file!
// For reasons or work-arounds, read below.
#endif

Also, both the template declarations and definitions should go into the same file. One exception is when you instantiate that template to some type in the source file at where the template definition is.

Something like this.

#include "this_template.h"

template <typename T>
// all sorts of definitions...

// Explicit instantiate this template!!!!
template class abcBaseClass<Your_Type_Goes_Here>;

Note, a fundamental flaw with this approach is that, you can only use the type you explicitly instantiate in this source file everywhere else in your program. Attempting to instantiate this template with some other type will cause the linker complain about not able to find the matching definition.

If you insist on both the template being generic and having the definition of your template class somewhere else. You can put the definition into another header file, just call it something like this_template_impl.h and include this_template.h in this_template_impl.h

Then, in your source file, instead of #include "this_template.h", you write #include "this_template_impl.h

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
Jimmy Lu
  • 4,810
  • 7
  • 25
  • 30
  • Hey thanks a lot for that. I am trying to get it done in one file right now and I was hoping how the definition is done... Is this right for the for mat you stated? abcDerivedClass::getvalue(char* name) – vadugs Oct 18 '12 at 19:59
1

You can put the definition in a .cpp file, but it's more trouble and not the way templates are usually done.

You need some extra code in the .cpp to convince the compiler to generate the functions with the necessary template parameter filled in. One way is to just use the function somehow:

mytypename abcDerivedClass<mytypename>::getvalue(char* name){

}

void dummy()
{
    abcDerivedClass<double> temp;
    temp->getvalue(NULL);
}

There's no need to actually call the dummy function, just having it there (after the template definition) is sufficient.

I'm sure there's another way to explicitly instantiate a template, but since I don't do this I can never remember.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
0

NO this isn't the correct way:

It should be done this way:

#ifndef  ........
#define .....
 template <class T>
 class abcBaseClass:public abcDerivedClass{
 public:
     T getvalue(char*)
};

#endif

and in the .cpp file: template T abcBaseClass::getvalue(char * ch){ }

The reason your code isn't correct is because typename is a C++ keyword. And must throw an error during compilation

You can also use:

#ifndef  ........
#define .....
 template <typename T>
 class abcBaseClass:public abcDerivedClass{
 public:
     T getvalue(char*)
};
#endif

and in the C++ file:

template<class T>
T abcBaseClass<T>::getvalue(char * ch){
}
Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • well, you can't really put definition of a template into a .cpp file like other things in C++. There is a work-around, but it's still different from how you normally separate header/source files – Jimmy Lu Oct 18 '12 at 18:12