I have this source code which allows me to cast a Point<float>
to Point<double>
:
template<class T> struct Point{
template <typename NewType> Point<NewType> cast() const{
return Point<NewType>();
}
};
int main(){
Point<float> p1;
Point<double> p2;
p2 = p1.cast<double>();
return 0;
}
This source code compiles well. Now, I add the following class and I have a compilation error at the line that does the cast:
template <class T> struct PointContainer{
void test(){
Point<T> p1;
Point<double> p2;
p2 = p1.cast<double>(); //compilation error
}
};
Compilation error: error: expected primary-expression before ‘double’
.
Why do I get this error and how can I solve it?
Short answer: you need to add the keyword template
right after the member access operator (the dot) in the line that is giving you the error.
Long answer: in PointContainer<T>
, T is an unknown template variable. Since in C++ templates can have specializations that are allowed to be completely different from the base template, the compiler does not know if type Point<T>
has a member cast that is a function template before substituting T for an actual type. That is why you can use the cast in main: Point<float>
is a concrete type and the compiler knows that it does have that function template.
Since the compiler does not know the type of member that "cast" will be, it does not let you use operations that assume that it is a type, a template, or both. In order to do either you need to tell that to the compiler using the typename
and template
keywords. Imagine that in addition to your cast
function template there is a typedef T value_type
in Point<T>
:
Point<float>::value_type f = 1.0f; // OK
Point<T>::value_type f = 1.0f; // Bad, compiler does not identify that as a type
typename Point<T>::value_type f = 1.0f; // OK
Point<float> pf;
Point<T> pT;
Point<double> pd1 = pf.cast<double>(); // OK
Point<double> pd2 = pT.cast<double>(); // Bad, compiler does not know cast is a template
Point<double> pd3 = pT.template cast<double>(); // OK
Point<T>
is a dependent-name (it depends on the template parameter T
), so the compiler does not really know what Point<T>::cast
is:
Point<T>::cast
could be an attribute, then p1.cast <
would be seen as a comparison with what's next.Point<T>::cast
could be a template (your case).Since the compiler cannot know, it assumes the first one, hence your error (you cannot compare something with a type). To solve this, you need to explicitly tell the compiler that p1.cast
is a templated method:
p2 = p1.template cast<double>();
For more information, see this question: Where and why do I have to put the "template" and "typename" keywords?
p2 = p1.cast<double>();
needs to be
p2 = p1.template cast<double>();
The reason for that can be found at Where and why do I have to put the "template" and "typename" keywords?.
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