提问人:BCS 提问时间:12/3/2022 最后编辑:BCS 更新时间:12/3/2022 访问量:61
模板类型(静态)包装函数?
Template type to (statically) wrap a function?
问:
C++ 标准是否定义了将函数包装在类型中的实用程序(与将其包装在值中不同)?
在谷歌上搜索了一堆看起来相关的名字后,我什么也没找到,但话又说回来,我知道一些我永远不会猜到名字的事情。
编辑:
- 我已经知道如何获得一个可以动态接受函数值的类型(或者一个好的旧函数指针,如 ),但它特别从类型中排除了我最想包含的一件事:要调用的实际函数。
std::function
int(*f)(int)
- 我已经知道如何从函数的名称 () 中获取函数的类型,这不是我想要的,原因与上面列出的相同。
decltype(fn)
我发现自己需要创建一个与函数完全匹配的类型(在我的情况下,来自第 3 部分库的 C 函数)。理想情况下,该类型在任何时候使用时都应该内联为零。作为一次性的,这很容易:operator()
foo
struct foo_t {
ret_t operator()(SomeType t, int i) {
return foo(t, i);
}
};
但是,至少在一种情况下,需要对一堆不同的函数执行此操作:删除器,同时与不透明句柄(例如来自 C 库)交互:std::unique_ptr<T,D>
std::unique_ptr<FILE*, fclose_t> f(fopen(n, "r"));
std::unique_ptr<obj*, free_t> o((obj*)malloc(sizeof(obj)));
...
与其自己定义 、 等,不如说我想做的是这样的:fclose_t
free_t
std::unique_ptr<FILE*, type_fn<fclose>> f(fopen(n, "r"));
std::unique_ptr<obj*, type_fn<free>> o((obj*)malloc(sizeof(obj)));
...
这还不难......如果您乐于定义自己:type_fn
template<auto *f> struct fn_type {
template<class... A>
auto operator() (A&&... a) {
return f(std::forward<A>(a)...);
}
};
这让我回到了开头的问题:C++是否定义了这样的东西?
答:
0赞
Ranoiaetep
12/3/2022
#1
这甚至不是那么难......如果你乐于定义自己......
type_fn
实际上,您不应该从标准库中获取函数的地址(有一些例外),因为库可能会对函数进行与函数的正常使用兼容的更改,但不会与获取其地址兼容(例如,添加具有默认值的参数,或向重载集添加重载)。
事实上,从 C++20 开始,明确禁止从标准库中获取函数的地址。更多信息可以在这里找到:我可以获取标准库中定义的函数的地址吗?
这意味着你不能写类似 .type_fn<fclose>
您的解决方案是使用 lambda,因为每个 lambda 的类型保证是唯一的:
auto deleter = [](auto *p){ std::fclose(p); };
现在,您可以在任何需要为其指定类型的位置使用:decltype(deleter)
auto f = std::uniqe_ptr<std::FILE, decltype(deleter)>(std::fopen("file", "r"));
如果您只需要一次此删除器,则还可以在模板参数中定义 lambda:
std::uniqe_ptr<std::FILE, decltype(
[](auto *p){ std::fclose(p); }
)>(std::fopen("file", "r"));
评论
0赞
BCS
12/4/2022
从C++11到C++17,最后一种形式是非法的:N4659 8.1.5(2)。即使是第一种形式在 C++20 N4659 8.1.5.1 (11) 之前也不起作用——C++20 似乎消除了这两个限制。强制 >=C++20 是不可预测的。A lambda-expression shall not appear in an unevaluated operand (Clause 8), in a template-argument, in an alias-declaration, in a typedef declaration, [...]
The closure type associated with a lambda-expression has no default constructor
评论
decltype
decltype
std::