无法将 subclass 的模板转换为另一个 base class 的模板,即使转换存在
Can't convert template of subclass to another template of base class even though conversion exists
在下面的代码中:
class Class {
};
class Subclass : public Class {
};
template<typename T>
class Template1 {
public:
};
template<typename T>
class Template2 {
public:
template<typename Y>
Template2(const Template1<Y>& t1)
{
}
};
Template2<Class> f1(Template2<Class>& t2) {
return Template1<Subclass>();
}
Template2<Class> f2(Template2<Class> t2) {
return Template1<Subclass>();
}
int main() {
f1(Template1<Subclass>()); // error C2664: 'Template2<Class> f1(Template2<Class> &)': cannot convert argument 1 from 'Template1<Subclass>' to 'Template2<Class> &'
f2(Template1<Subclass>()); // OK
f1(Template2<Class>(Template1<Subclass>())); // OK
}
如果我从函数中删除引用或自己进行转换,一切都很好,但编译器似乎不想自己从 Template1
转换为 Template2&
。为什么?
问题
您的 f1()
函数需要一个 lvalue for the argument passed by reference. Unfortunately, the implicit conversion produces a temporary value that cannot be used as an lvalue. This causes the C2664 error message。
解决方案
您只需将函数定义为
,避免尝试引用转换产生的临时值
Template2<Class> f1(const Template2<Class>& t2) { // const & can be used for temp
return Template1<Subclass>();
}
或者,更好,如
Template2<Class> f1(Template2<Class>&& t2) { // && is meant for exactly such cases
return Template1<Subclass>();
}
您甚至可以有两个这样的构造函数,一个用于左值引用 &
,一个用于右值引用 &&
,如果区别很重要的话。这里有一个 online demo
在下面的代码中:
class Class {
};
class Subclass : public Class {
};
template<typename T>
class Template1 {
public:
};
template<typename T>
class Template2 {
public:
template<typename Y>
Template2(const Template1<Y>& t1)
{
}
};
Template2<Class> f1(Template2<Class>& t2) {
return Template1<Subclass>();
}
Template2<Class> f2(Template2<Class> t2) {
return Template1<Subclass>();
}
int main() {
f1(Template1<Subclass>()); // error C2664: 'Template2<Class> f1(Template2<Class> &)': cannot convert argument 1 from 'Template1<Subclass>' to 'Template2<Class> &'
f2(Template1<Subclass>()); // OK
f1(Template2<Class>(Template1<Subclass>())); // OK
}
如果我从函数中删除引用或自己进行转换,一切都很好,但编译器似乎不想自己从 Template1
转换为 Template2&
。为什么?
问题
您的 f1()
函数需要一个 lvalue for the argument passed by reference. Unfortunately, the implicit conversion produces a temporary value that cannot be used as an lvalue. This causes the C2664 error message。
解决方案
您只需将函数定义为
,避免尝试引用转换产生的临时值Template2<Class> f1(const Template2<Class>& t2) { // const & can be used for temp
return Template1<Subclass>();
}
或者,更好,如
Template2<Class> f1(Template2<Class>&& t2) { // && is meant for exactly such cases
return Template1<Subclass>();
}
您甚至可以有两个这样的构造函数,一个用于左值引用 &
,一个用于右值引用 &&
,如果区别很重要的话。这里有一个 online demo