Не удается преобразовать шаблон подкласса в другой шаблон базового класса, даже если преобразование существует - PullRequest
0 голосов
/ 02 марта 2019

В следующем коде:

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& сам по себе.Почему?

1 Ответ

0 голосов
/ 02 марта 2019

Проблема

Ваша функция f1() нуждается в lvalue для аргумента, переданного по ссылке.К сожалению, неявное преобразование создает временное значение, которое нельзя использовать в качестве lvalue.Это вызывает сообщение об ошибке C2664 .

Решение

Вам просто не нужно пытаться ссылаться на временное значение, полученное в результате преобразования, определяя вашу функцию как

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>();
}

У вас может быть даже два таких конструктора, один для ссылок lvalue & и один для ссылок rvalue &&, если это может быть важно для изменения.Здесь онлайн демо

...