带有 C++11+ unique_ptr 的 Libevent
Posted
技术标签:
【中文标题】带有 C++11+ unique_ptr 的 Libevent【英文标题】:Libevent with C++11+ unique_ptr 【发布时间】:2017-02-01 11:34:14 【问题描述】:我最近尝试使用 std::unique_ptr
和自定义删除器包装 libdbus
类型和 libevent
类型以简化代码,但这些库出现错误:
/opt/cross/armv7hl-meego-linux-gnueabi/include/c++/4.8.3/bits/unique_ptr.h:65:22: error: invalid application of 'sizeof' to incomplete type 'sockets::libev::event_base'
static_assert(sizeof(_Tp)>0,
^
代码很简单:
namespace sockets
// ... unix sockets stuff
namespace libev
#include <event.h>
// libev
// sockets
class A
public:
void run()
using namespace sockets;
using namespace sockets::libev;
using UniqueEventBase = std::unique_ptr<event_base>;
// ...
;
那么在这个例子中我该如何为event_base
struct 编写RAII-wrappers 呢?
附:我发现event_base
结构是在event2/event.h
中前向声明的。所以没有选项来包装它?
【问题讨论】:
【参考方案1】:由于std::unique_ptr
不会对删除器进行类型擦除,并且the default deleter 不适用于不完整的类型,因此您需要提供替代删除器作为类型签名的一部分:
struct EventBaseDeleter
void operator()(event_base* ptr) const
sockets::libev::event_base_free(ptr);
;
using UniqueEventBase = std::unique_ptr<event_base, EventBaseDeleter>;
【讨论】:
【参考方案2】:标头 event2/event.h
故意不定义 event_base
以便实现保持私有。
CPP Reference 说:
std::unique_ptr 可以为不完整的类型 T 构造,以便于在 pImpl 习语中用作句柄。如果使用默认删除器,则 T 必须在代码中调用删除器的位置完成,这发生在 std::unique_ptr 的析构函数、移动赋值运算符和重置成员函数中。
因此,您需要通过提供自己的删除器作为模板的第二个参数来避免使用默认删除器。
这很有意义,尤其是在这种情况下,您希望调用event_base_free
而不是尝试delete
。
【讨论】:
以上是关于带有 C++11+ unique_ptr 的 Libevent的主要内容,如果未能解决你的问题,请参考以下文章
在 c++11 模式下使用带有仅移动参数的 QtConcurrent::run