【问题标题】:Deduce weak_ptr argument from shared_ptr从 shared_ptr 推导出 weak_ptr 参数
【发布时间】:2015-04-14 17:11:58
【问题描述】:

以下给我编译器错误:

无法推导出 'const std::weak_ptr<_ty> &' 的模板参数 来自'std::shared_ptr'

#include <memory>

class Foo
{
public:

    template<typename R>
    void Bar(std::weak_ptr<R> const & p)
    {
        p;
    }
};

int main(void)
{
    auto foo = Foo();
    auto integer = std::make_shared<int>();

    foo.Bar(integer);
}

我试过了,

template<typename R>
void Bar(std::weak_ptr<R::element_type> const & p)
{

}

,这似乎在语法上不正确。以下工作,但我想知道是否有可能在 p 中进行转换,而不创建另一个临时?

template<typename R>
void Bar(R const & p)
{
    auto w = std::weak_ptr<R::element_type>(p);
}

为了清楚起见,我想明确声明该函数应该采用 shared 或 weak_ptr,所以我不喜欢 R const & p 解决方案。

为了完整起见,这当然也可以:

template<typename R>
void Bar(std::shared_ptr<R> const & p)
{
    auto w = std::weak_ptr<R>(p);
}

【问题讨论】:

  • element_type 是 shared_ptr (trait) 的类型。在这种情况下, 是一个 shared_ptr。至少这似乎是类型推断过程告诉我的。所以在示例中 element_type 将是“int”。

标签: c++ shared-ptr weak-ptr


【解决方案1】:

std::weak&lt;R&gt; 的模板参数R 不能从std::shared_ptr&lt;A&gt; 的实例推导出来,因为转换构造函数(采用std::shared_ptr&lt;Y&gt;)是一个构造函数模板,这意味着Y 可以是任何东西——而且存在是没有办法从Y推导出R(推导出为A)。看看转换构造函数。

你可以这样写:

template<typename T>
auto make_weak(std::shared_ptr<T> s) ->  std::weak_ptr<T>
{
  return { s };
}

然后称它为:

foo.Bar( make_weak(integer) );

【讨论】:

    【解决方案2】:

    使用 C++ 17 的 class template deduction,现在应该是合法的:

    auto shared = std::make_shared< int >( 3 );
    auto weak = std::weak_ptr( shared );
    std::weak_ptr weak2( shared );
    

    coliru 上查看。

    【讨论】:

    【解决方案3】:

    您需要处理两种(语言方面)完全不相关的类型,因此您需要提供两种重载,一种用于每种指针类型。然后 shared_ptr 版本可以通过在其调用中提供正确的T 来调用weak_ptr 版本。

    【讨论】:

      【解决方案4】:

      因为你比编译器聪明,你必须帮助它推断出那个类型。

      观察你的这部分代码。

      template<typename R>
      void Bar(std::weak_ptr<R> const & p)
      

      知道,对于每个可能存在的R恰好有一个R存在从std::shared_ptr&lt;int&gt; 的隐式转换。您可能没有在其他地方编写任何适用于此的转换运算符。

      您的 C++ 编译器不会知道或假设这一点。所以你应该把函数称为:

      foo.Bar( std::weak_ptr<int>{integer} );
      

      或尝试 Mark B 的答案中的方法。

      【讨论】:

        猜你喜欢
        • 2011-06-26
        • 1970-01-01
        • 1970-01-01
        • 2017-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        相关资源
        最近更新 更多