【发布时间】:2014-04-28 11:47:11
【问题描述】:
我正在尝试将 std::unique_ptr 与自定义删除器一起使用,以简化管理从各种 C API 返回给我的句柄的生命周期。这在理论上很好,但我正在努力寻找一种在运行时最佳的方法,并且没有为每种包装类型提供大量样板。
例如,考虑一些不透明类型 foo,必须通过将其指针传递给 destroy_foo 来释放它:
// approach 1: pass destroy_foo at runtime (bad for performance)
using foo_ptr = std::unique_ptr<foo, decltype(&destroy_foo)>;
foo_ptr bar{create_foo(...), destroy_foo};
// approach 2: make a deleter type (verbose - for many types)
struct foo_deleter
{
void operator()(foo* p)
{
destroy_foo(p);
}
};
using foo_ptr = std::unique_ptr<foo, foo_deleter>;
foo_ptr bar{create_foo(...)};
第一种方法对编译器来说很难优化,因为我正在传递一个函数指针,所以它被淘汰了。第二种方法似乎不必要地冗长。我有很多这样的类型我想管理,并且为每个类型手动创建一个类是很痛苦的。
如何定义一个接受destroy_foo 并为我提供与foo_deleter 等效的类型的类模板?或者是否有标准库模板可以做到这一点?
// best of both worlds - to_obj<Func> makes foo_deleter from destroy_foo...
using foo_ptr = std::unique_ptr<foo, to_obj<destroy_foo>>;
foo_ptr bar{create_foo(..)};
因此,给定任何函数,模板都会定义一个带有 operator() 的类,它只是将所有参数转发给函数,并返回结果。
【问题讨论】:
-
当我们考虑到它用于处理资源的终止(释放内存、关闭文件句柄……)时,从存储指针进行间接调用的性能真的很重要吗?
-
是的,它们并不总是重量级资源。除了额外的 CPU 时间之外,还有一个事实是每个指针的大小可能会翻倍。
标签: c++ templates c++11 template-meta-programming