我有这个源代码,允许我将Point<float>
投射到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;
}
此源代码编译良好。现在,我添加了以下类,并且在执行转换的行中有一个编译错误:
template <class T> struct PointContainer{
void test(){
Point<T> p1;
Point<double> p2;
p2 = p1.cast<double>(); //compilation error
}
};
编译错误:error: expected primary-expression before ‘double’
。
为什么我会收到此错误,如何解决?
答案 0 :(得分:8)
简短回答:您需要在提供错误的行中的成员访问运算符(点)之后添加关键字template
。
答案很长:在PointContainer<T>
中,T是一个未知的模板变量。由于在C ++模板中可以具有允许与基本模板完全不同的特化,因此在将T替换为实际类型之前,编译器不知道类型Point<T>
是否具有作为函数模板的成员强制转换。这就是为什么你可以在main中使用强制转换:Point<float>
是一个具体的类型,编译器知道它确实有这个函数模板。
由于编译器不知道“强制转换”成员的类型,因此它不允许您使用假定它是类型,模板或两者的操作。为了做到这一点,您需要使用typename
和template
关键字告诉编译器。想象一下,除cast
功能模板外,typedef T value_type
中还有一个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
答案 1 :(得分:4)
Point<T>
是依赖名称(它取决于模板参数T
),因此编译器并不真正知道Point<T>::cast
是什么:< / p>
Point<T>::cast
可能是一个属性,然后p1.cast <
将被视为与下一个属性的比较。Point<T>::cast
可以是模板(您的情况)。由于编译器无法知道,它假设第一个,因此你的错误(你无法比较某种类型的东西)。要解决此问题,您需要明确告诉编译器p1.cast
是模板化方法:
p2 = p1.template cast<double>();
有关详细信息,请参阅此问题:Where and why do I have to put the "template" and "typename" keywords?
答案 2 :(得分:1)
p2 = p1.cast<double>();
需要
p2 = p1.template cast<double>();
可以在Where and why do I have to put the "template" and "typename" keywords?找到原因。
答案 3 :(得分:0)
在melpomene后期链接中接受的答案给出了答案。
您需要使用template
关键字。
template <class T> struct PointContainer{
void test(){
Point<T> p1;
Point<double> p2;
p2 = p1.template cast<double>();
}
};
答案 4 :(得分:0)
正如其他人所说的那样,你的问题是你需要告诉编译器,依赖模板是模板,并且使用了模板关键字。
y=x.template cast<Y>();
解决这个问题的方法是让它不再是依赖模板。
最简单的方法是编写一个自由函数
template<class D, class S>
Point<D> cast( Point<S> const& s ){ return s.template cast<D>(); }
现在你可以自由使用:
y = cast<Y>(x);
没有恼人的template
关键字,因为cast
是模板的事实不再依赖。