c++ 模板类型是否(静态) Package 函数?

7tofc5zh  于 2022-12-05  发布在  其他
关注(0)|答案(1)|浏览(116)

C++标准是否定义了将函数 Package 在类型中(与将其 Package 在值中不同)的实用程序?
在谷歌上搜索了一堆看起来相关的名字后,我没有找到任何东西,但话又说回来,我知道一些我永远猜不到的名字。

编辑:

  • 我已经知道如何获得一个可以动态获取函数值的类型(std::functionint(*f)(int)之类的旧函数指针),但这特别排除了我最想包含的一个东西:要调用的实际函数。
  • 我已经知道如何从函数名(decltype(fn))中获取函数的类型,但这不是我想要的,原因与上面列出的相同。

我发现自己需要创建一个类型,它的operator()与函数foo完全匹配(在我的例子中,是第三方库中的一个C函数)。理想情况下,该类型应该在任何时候使用时都内联到空。作为一次性的,这很容易:

struct foo_t {
  ret_t operator()(SomeType t, int i) {
    return foo(t, i);
  }
};

但是,至少有一种情况需要对一组不同的函数执行此操作:std::unique_ptr<T,D>的deleters,同时与不透明句柄(例如,来自C库)接口:

std::unique_ptr<FILE*, fclose_t> f(fopen(n, "r"));
std::unique_ptr<obj*, free_t> o((obj*)malloc(sizeof(obj)));
...

我不想自己定义fclose_tfree_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++定义了类似的东西吗 *

e4eetjau

e4eetjau1#

如果您愿意自己定义type_fn,这并不难......
实际上,您不应该从标准库中获取函数的地址(有一些例外),因为库可能会对函数进行更改,这些更改与函数的正常使用兼容,但与获取其地址不兼容(例如,添加带有默认值的参数,或向重载集添加重载)。
实际上,从C++20起,从标准库中获取函数的地址就被明确禁止了。更多信息可以在这里找到:Can I take the address of a function defined in standard library?
也就是说你不能写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"));

如果你只需要这个deleter一次,你也可以只在模板参数中定义lambda:

std::uniqe_ptr<std::FILE, decltype(
    [](auto *p){ std::fclose(p); }
)>(std::fopen("file", "r"));

相关问题