#include <utility>
#include "iostream"
template<class Vty>
class Base {
public:
Base(Vty value) : _baseValue(std::move(value)) {}
virtual auto print() -> void {
std::cout << "This class is Base, " << _baseValue << std::endl;
}
protected:
Vty _baseValue;
};
template<class Vty>
class Derived : public Base<Vty> {
public:
Derived(Vty value) : Base<Vty>(value) {}
auto print() -> void override {
std::cout << "This class is Derived," << this->_baseValue << std::endl;
}
};
template<class Vty>
auto print(const std::shared_ptr<Base<Vty>> &instance) -> void {
instance->print();
}
int main(int argc, char **argv) {
auto base = std::make_shared<Base<std::string>>("this is value");
print(base); //this line is normal.
auto derived = std::make_shared<Derived<std::string>>("this is value");
print(derived); //this line will report an error.
}
Этот код сообщит об ошибке:
No matching function for call to 'print' candidate template ignored: could not match 'Base' against 'Derived'
Я пытался создать print такое ощущение:
template<template<class>class Cty, class Vty, std::enable_if_t<std::is_convertible_v<Cty<Vty>, Base<Vty>>>* = nullptr>
auto print(const std::shared_ptr<Cty<Vty>> &instance) -> void {
instance->print();
}
Измените print вот так, и всё заработает, но что мне делать, если я хочу использовать функцию print, как раньше, или это невозможно? Хотите добавить несколько операторов?
Каков ваш ожидаемый результат?
Если вы хотите вызвать производную функцию, то почему бы просто не void print(const std::shared_ptr<auto> &instance) -> void { instance->print(); }. Если только вам действительно не нужен print_base()
Я попробовал это, и, кажется, это работает: print(std::static_pointer_cast<Base<std::string>>(derived));
Как сказал @kiner_shah, если вам действительно нужно вызвать базовую функцию, поставьте std::static_pointer_cast внутри print()
Ваш вопрос не ясен. Вы знаете, как переписать print, чтобы это работало. Вы спрашиваете, как вызвать старую версию print? Попробуйте print<std::string>(derived).





Вывод шаблона происходит до преобразования параметров. В вашем случае вычет Vty не предусмотрен, потому что Derived<std::string> не является Base<std::string>.
Вы можете явно передать тип в шаблон, и тогда ему не придется его выводить, поэтому может произойти неявное преобразование указателя.
print<std::string>(derived);
Альтернативно, вы можете явно преобразовать и разрешить выведение шаблона.
print(std::static_pointer_cast<Base<std::string>>(derived));
Опять же, использование завершающего типа возвращаемого значения, когда вы уже знаете тип возвращаемого значения, не имеет смысла. Замените
auto print() -> void overrideнаvoid print() override