我有这个源代码,允许我投射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;
}
Run Code Online (Sandbox Code Playgroud)
这个源代码编译得很好.现在,我添加以下类,我在执行转换的行中有一个编译错误:
template <class T> struct PointContainer{
void test(){
Point<T> p1;
Point<double> p2;
p2 = p1.cast<double>(); //compilation error
}
};
Run Code Online (Sandbox Code Playgroud)
编译错误:error: expected primary-expression before ‘double’.
为什么我会收到此错误,如何解决?
简短回答:您需要template在提供错误的行中的成员访问运算符(点)之后添加关键字.
答案很长:在PointContainer<T>,T是一个未知的模板变量.由于在C++模板中可以具有允许与基本模板完全不同的特化,因此Point<T>在将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
Run Code Online (Sandbox Code Playgroud)
Point<T>是一个依赖名称(它取决于模板参数T),所以编译器并不真正知道是什么Point<T>::cast:
Point<T>::cast可能是一个属性,然后p1.cast <将被视为与接下来的比较。Point<T>::cast 可能是一个模板(你的情况)。由于编译器不知道,它假定第一个,因此您的错误(您无法将某些内容与类型进行比较)。要解决这个问题,您需要明确告诉编译器这p1.cast是一个模板化方法:
p2 = p1.template cast<double>();
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅此问题:我必须将“模板”和“类型名称”关键字放在哪里以及为什么要放?
链接的 Melpomene 帖子中接受的答案为您提供了答案。
您需要使用template关键字。
template <class T> struct PointContainer{
void test(){
Point<T> p1;
Point<double> p2;
p2 = p1.template cast<double>();
}
};
Run Code Online (Sandbox Code Playgroud)