即使转换存在,也无法将子类的模板转换为基类的另一个模板

问题描述 投票:1回答:1

在以下代码中:

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&。为什么?

c++ templates constructor parameter-passing implicit-conversion
1个回答
1
投票

The problem

你的f1()函数需要一个lvalue作为参考传递的参数。不幸的是,隐式转换产生的临时值不能用作左值。这导致C2664 error message

The solution

通过将函数定义为,您只需要避免尝试引用转换产生的临时值

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

© www.soinside.com 2019 - 2024. All rights reserved.