std::shared_ptr 在按引用传递时如何跨 class 层次结构进行转换?

How does std::shared_ptr converts across class hierarchy when passing by reference?

看着 20.8.2.2 Class 模板 shared_ptr [util.smartptr.shared] 我意识到std::shared_ptr 具有模板复制构造函数和赋值运算符,当且仅当 Derived* 可转换为 Base* 时才允许从 shared_ptr<Derived> 转换为 shared_ptr<Base>。这些转换(以我的理解)仅通过模板化的复制构造函数和赋值运算符完成。但是,我似乎也可以将 shared_ptr<Derived> 传递给采用 shared_ptr<Base>& 的函数(即,通过引用传递)。好像应该有隐式转换运算符,但是按照标准有none。

下面的代码阐明了我的意思:

#include <iostream>
#include <memory>

struct Base {};
struct Derived: Base {};

void f(const std::shared_ptr<Base>& ) {}

int main()
{
    std::shared_ptr<Derived> spDerived(new Derived);

    // conversion below is OK, via template copy ctor
    std::shared_ptr<Base> spBase(spDerived); 
    // also OK, via template copy assignment operator
    spBase = spDerived; 

    // why is this OK? Cannot see any conversion operators in
    // 20.8.2.2 Class template shared_ptr [util.smartptr.shared]
    f(spDerived); 
}

我的问题: 在这种情况下,谁在调用 f(spDerived) 中执行从 shared_ptr<Derived>shared_ptr<Base> 的转换? (因为编译器 shared_ptr<Derived>shared_ptr<Base> 没有任何关系,即使 DerivedBase 的子代)

通过模板复制构造函数创建了一个临时文件,该副本就是所引用的。 ctor 是隐式的,因此在这种情况下可以合法地调用它。从根本上说,此调用与 f(std::string); f("hello"); 之间没有区别。完全相同的机制在起作用。这是一个常规的隐式转换。