【问题标题】:Unable to compile with unique_ptr and deleter无法使用 unique_ptr 和 deleter 进行编译
【发布时间】:2014-02-27 17:37:48
【问题描述】:

我在使用 unique_ptr 和删除器时遇到问题。以下内容无法编译:

unique_ptr<RSA> rsa(RSA_new(), ::RSA_free);
unique_ptr<RSA> rsa(RSA_new(), ptr_fun(RSA_free));

编译错误如下所示。

shared_ptr 工作正常,但在将其中一个指针分配到另一个结构时我需要 release (并且shared_ptr 不友好)。

我在 Debian 7.3 (x64) 上使用 GCC 4.7。一切都已完全修补。

任何想法我做错了什么?


../source/ac-pki.cpp:461:46: error: no matching function for call to ‘std::unique_ptr<rsa_st>::unique_ptr(RSA*, void (&)(RSA*))’
../source/ac-pki.cpp:461:46: note: candidates are:
In file included from /usr/include/c++/4.7/memory:86:0,
                 from /home/jwalton/test/include/ac-common.h:39,
                 from ../source/ac-pki.cpp:1:
/usr/include/c++/4.7/bits/unique_ptr.h:164:2: note: template<class _Up, class> std::unique_ptr::unique_ptr(std::auto_ptr<_Up>&&)
/usr/include/c++/4.7/bits/unique_ptr.h:164:2: note:   template argument deduction/substitution failed:
../source/ac-pki.cpp:461:46: note:   mismatched types ‘std::auto_ptr<_Up>’ and ‘RSA* {aka rsa_st*}’
In file included from /usr/include/c++/4.7/memory:86:0,
                 from /home/jwalton/test/include/ac-common.h:39,
                 from ../source/ac-pki.cpp:1:
/usr/include/c++/4.7/bits/unique_ptr.h:155:2: note: template<class _Up, class _Ep, class> std::unique_ptr::unique_ptr(std::unique_ptr<_Up, _Ep>&&)
/usr/include/c++/4.7/bits/unique_ptr.h:155:2: note:   template argument deduction/substitution failed:
../source/ac-pki.cpp:461:46: note:   mismatched types ‘std::unique_ptr<_Up, _Ep>’ and ‘RSA* {aka rsa_st*}’
In file included from /usr/include/c++/4.7/memory:86:0,
                 from /home/jwalton/test/include/ac-common.h:39,
                 from ../source/ac-pki.cpp:1:
/usr/include/c++/4.7/bits/unique_ptr.h:142:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp> = std::unique_ptr<rsa_st>]
/usr/include/c++/4.7/bits/unique_ptr.h:142:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/4.7/bits/unique_ptr.h:136:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::nullptr_t = std::nullptr_t]
/usr/include/c++/4.7/bits/unique_ptr.h:136:17: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/4.7/bits/unique_ptr.h:130:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp>::pointer = rsa_st*; typename std::remove_reference<_To>::type = std::default_delete<rsa_st>]
/usr/include/c++/4.7/bits/unique_ptr.h:130:7: note:   no known conversion for argument 2 from ‘void(RSA*) {aka void(rsa_st*)}’ to ‘std::remove_reference<std::default_delete<rsa_st> >::type&& {aka std::default_delete<rsa_st>&&}’
/usr/include/c++/4.7/bits/unique_ptr.h:125:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp>::pointer = rsa_st*; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<rsa_st>&]
/usr/include/c++/4.7/bits/unique_ptr.h:125:7: note:   no known conversion for argument 2 from ‘void(RSA*) {aka void(rsa_st*)}’ to ‘std::conditional<false, std::default_delete<rsa_st>, const std::default_delete<rsa_st>&>::type {aka const std::default_delete<rsa_st>&}’
/usr/include/c++/4.7/bits/unique_ptr.h:120:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp>::pointer = rsa_st*]
/usr/include/c++/4.7/bits/unique_ptr.h:120:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/4.7/bits/unique_ptr.h:114:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>]
/usr/include/c++/4.7/bits/unique_ptr.h:114:17: note:   candidate expects 0 arguments, 2 provided
../source/ac-pki.cpp:550:91: error: cannot convert ‘std::unique_ptr<rsa_st>::pointer {aka rsa_st*}’ to ‘EVP_PKEY* {aka evp_pkey_st*}’ for argument ‘2’ to ‘int PEM_write_PKCS8PrivateKey(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, int (*)(char*, int, int, void*), void*)’
make: *** [source/ac-pki.o] Error 1

【问题讨论】:

  • std::shared_ptr 使用一种时髦的类型擦除技术来存储它的删除器,因此指针类型shared_ptr&lt;foo&gt; 可以独立于删除器类型。 unique_ptr 没有:它的设计目的是零开销,所以删除器类型必然编码在指针类型中。

标签: c++ c++11 compiler-errors unique-ptr


【解决方案1】:

你还需要给出删除器的类型

std::unique_ptr<RSA, void (*)(RSA*)> rsa(RSA_new(), ::RSA_free);

否则,std::unique_ptr 使用 std::default_delete

【讨论】:

  • 我强烈建议将这样的函数指针包装在 functionoid 中,这使得 unique_ptr 更快更小。 auto RSA_Deleter = [](RSA*p)-&gt;void{::RSA_free(p);};
【解决方案2】:

删除器的类型是unique_ptr's 类型的一部分。所以把你的代码改成

std::unique_ptr<RSA, decltype(&::RSA_free)> p(RSA_new(), ::RSA_free);

或者,减少冗长

using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;
RSA_ptr rsa(RSA_new(), ::RSA_free);

【讨论】:

  • 哦,太好了。谢谢。
猜你喜欢
  • 2019-02-10
  • 2020-08-19
  • 2014-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-06
  • 1970-01-01
相关资源
最近更新 更多