mar*_*ack 5 c++ templates template-meta-programming c++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(...)};
Run Code Online (Sandbox Code Playgroud)
第一种方法很难让编译器优化,因为我传递了一个函数指针,所以它被淘汰了。第二种方法似乎不必要地冗长。我有很多这样的类型想要管理,为每个类型手动创建一个类是很痛苦的。
如何定义一个类模板,它接受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(..)};
Run Code Online (Sandbox Code Playgroud)
因此,给定任何函数,模板将定义一个类,该类operator()
简单地将所有参数转发给函数,并返回结果。
就像是
template<typename T, void (*func)(T*)>
struct Deleter{
void operator()(T* t) { func(t); }
};
Run Code Online (Sandbox Code Playgroud)
??
或者如果你想要更强大的东西
template <typename t>
struct function_traits;
template <typename R, typename A>
struct function_traits<R (*)(A)>
{
using t_ret = R;
using t_arg = A;
};
template <typename F, F* f>
struct Functor
{
using FT = function_traits<F*>;
typename FT::t_ret operator()(typename FT::t_arg a) {
return f(a);
}
};
void mydeleter(int*);
#define FUNCTOR(F) Functor<decltype(F),&F>
Run Code Online (Sandbox Code Playgroud)
或者充分利用 C++11 的力量
template <typename F, F* f>
struct Functor
{
template<typename... A>
auto operator()(A&&... a) -> decltype(f(std::forward<A>(a)...)) {
return f(std::forward<A>(a)...);
}
};
#define FUNCTOR(F) Functor<decltype(F),&F>
Run Code Online (Sandbox Code Playgroud)