从 shared_ptr 推导出 weak_ptr 论点
Deduce weak_ptr argument from shared_ptr
以下是编译器错误:
could not deduce template argument for 'const std::weak_ptr<_Ty> &'
from '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);
}
明确地说,我想明确声明函数应该采用共享或 weak_ptr,所以我不喜欢 R const & p 解决方案。
为了完整起见,这当然也有效:
template<typename R>
void Bar(std::shared_ptr<R> const & p)
{
auto w = std::weak_ptr<R>(p);
}
因为你比编译器更聪明,所以你必须帮助它推导出那个类型。
观察这部分代码。
template<typename R>
void Bar(std::weak_ptr<R> const & p)
你知道对于每一个可能存在的R
,恰好有一个R
其中存在从 std::shared_ptr<int>
的隐式转换。您可能没有在其他地方编写适用于此处的任何转换运算符。
您的 C++ 编译器不会知道或假设这一点。所以你应该调用这个函数:
foo.Bar( std::weak_ptr<int>{integer} );
或者试试 Mark B 的回答中的方法。
您需要处理两种(在语言方面)完全不相关的类型,因此您需要提供两种重载,一种用于每种指针类型。然后 shared_ptr 版本可以通过在其调用中提供正确的 T
来调用 weak_ptr 版本。
std::weak<R>
的模板参数 R
无法从 std::shared_ptr<A>
的实例中推导出来,因为转换构造函数(采用 std::shared_ptr<Y>
)是一个构造函数模板,它meansY
可以是任何东西——并且没有办法从 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) );
对于 C++ 17 的 class template deduction,这现在应该是合法的:
auto shared = std::make_shared< int >( 3 );
auto weak = std::weak_ptr( shared );
std::weak_ptr weak2( shared );
在 coliru 上查看。
以下是编译器错误:
could not deduce template argument for 'const std::weak_ptr<_Ty> &' from '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);
}
明确地说,我想明确声明函数应该采用共享或 weak_ptr,所以我不喜欢 R const & p 解决方案。
为了完整起见,这当然也有效:
template<typename R>
void Bar(std::shared_ptr<R> const & p)
{
auto w = std::weak_ptr<R>(p);
}
因为你比编译器更聪明,所以你必须帮助它推导出那个类型。
观察这部分代码。
template<typename R>
void Bar(std::weak_ptr<R> const & p)
你知道对于每一个可能存在的R
,恰好有一个R
其中存在从 std::shared_ptr<int>
的隐式转换。您可能没有在其他地方编写适用于此处的任何转换运算符。
您的 C++ 编译器不会知道或假设这一点。所以你应该调用这个函数:
foo.Bar( std::weak_ptr<int>{integer} );
或者试试 Mark B 的回答中的方法。
您需要处理两种(在语言方面)完全不相关的类型,因此您需要提供两种重载,一种用于每种指针类型。然后 shared_ptr 版本可以通过在其调用中提供正确的 T
来调用 weak_ptr 版本。
std::weak<R>
的模板参数 R
无法从 std::shared_ptr<A>
的实例中推导出来,因为转换构造函数(采用 std::shared_ptr<Y>
)是一个构造函数模板,它meansY
可以是任何东西——并且没有办法从 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) );
对于 C++ 17 的 class template deduction,这现在应该是合法的:
auto shared = std::make_shared< int >( 3 );
auto weak = std::weak_ptr( shared );
std::weak_ptr weak2( shared );
在 coliru 上查看。