为什么shared_ptr到派生不隐式转换为shared_ptr到基



我不明白为什么在下面的代码中,shared_ptr<Derived<int>>没有隐式转换为shared_ptr<Base<int>>:

#include <memory>

template <typename T>
class Base {
};

template <typename T>
class Derived : public Base<T> {
};

template <typename T>
T foo(std::shared_ptr<Base<T>>) {
return T{};
}

void main() {
foo(std::make_shared<Base<int>>());
foo(std::make_shared<Derived<int>>());
}

我遇到了转换std::shared_ptr<派生>以const shared_ptr<基础>amp;,这似乎与我有关。我是否因为制作了函数的模板而出错?

我得到的错误是:

E0304没有函数模板的实例";foo";匹配参数列表

C2664’std::shared_ptr<基本<int>gt;foo<int>(std::shared_ptr<Base<int>>(":无法从"std::shared_ptr<派生<int>gt;'到'std::shared_ptr<基本<int>gt;'

这种行为的原因是foo是一个模板。注意,如果foo不是一个模板,那么一切都能正常工作:
int foo(std::shared_ptr<Base<int>>) {
return int{};
}

然而,当foo是一个模板时,编译器首先需要实例化foo,并且它希望能够实例化精确匹配,因为隐式转换在这一点上不适用。而这个实例化不能成功,从而导致错误。

解决这个问题的一种方法是使foo成为一个非常贪婪的模板,然后添加额外的可转换性约束。例如:

#include <memory>
template <typename T>
class Base {
public:
using Type = T;
};
template <typename T>
class Derived : public Base<T> {
};
template <typename T>
auto foo(T) -> std::enable_if_t<std::is_convertible_v<T, std::shared_ptr<Base<typename T::element_type::Type>>>, typename T::element_type>
{    
return typename T::element_type{};
}

int main() {
foo(std::make_shared<Derived<int>>()); //OK
foo(20); // error
}

注意,我已经向基类添加了一个Type成员。这不是严格必要的,但简化了代码。

相关内容

  • 没有找到相关文章

最新更新