Let's say I have a class based on a template ThingType
. In the header, I use this to typedef
a dependent type VectorThingType
. I'd like to return this from a method GetVectorOfThings()
. If I set VectorThingType
as the return type, I get a Does not name a type
error, as the type wasn't defined in this scope. Is there any way to do this without duplicating the code in the typedef
?
#include <vector>
#include <iostream>
template< typename ThingType >
class Thing
{
public:
ThingType aThing;
typedef std::vector< ThingType > VectorThingType;
VectorThingType GetVectorOfThings();
Thing(){};
~Thing(){};
};
template< typename ThingType >
//VectorThingType // Does not name a type
std::vector< ThingType > // Duplication of code from typedef
Thing< ThingType >
::GetVectorOfThings() {
VectorThingType v;
v.push_back(this->aThing);
v.push_back(this->aThing);
return v;
}
Template classes are instanced in the same way template functions are -- the compiler stencils out a copy upon demand, with the template parameter replaced by the actual data type the user needs, and then compiles the copy. If you don’t ever use a template class, the compiler won’t even compile it.
The “template class” command causes the compiler to explicitly instantiate the template class. In the above case, the compiler will stencil out both Array<int> and Array<double> inside of templates.cpp. Because templates.cpp is inside our project, this will then be compiled.
Template classes are ideal for implementing container classes, because it is highly desirable to have containers work across a wide variety of data types, and templates allow you to do so without duplicating code.
This isn’t necessary, but new programmers typically stumble when trying to do this for the first time due to the syntax, so an example is instructive. Each templated member function defined outside the class declaration needs its own template declaration.
template< typename ThingType >
auto // <-- defer description of type until...
Thing< ThingType >
::GetVectorOfThings()
-> VectorThingType // <-- we are now in the context of Thing< ThingType >
{
VectorThingType v;
v.push_back(this->aThing);
v.push_back(this->aThing);
return v;
}
Just came across another answer to this question, which doesn't involve c++11.
template< typename ThingType >
typename Thing< ThingType >::VectorThingType
Thing< ThingType >
::GetVectorOfThings()
{
VectorThingType v;
v.push_back(this->aThing);
v.push_back(this->aThing);
return v;
}
Basically involves assuring the compiler that you are, in fact, dealing with a type via typename
and then properly scoping the type using Thing< ThingType >::
. Could be useful if you are stuck with c++03 for some reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With