gpt4 book ai didi

c++ - 使用普通函数删除器构建 std::unique_ptr 的包装器

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:06:39 25 4
gpt4 key购买 nike

我正在尝试实现一个可以像这样使用的 std::unique_ptr 工厂:

auto fd = my_make_unique<fclose>(fopen("filename", "r"));

即,将删除函数作为模板参数传递。

我在 C++11 中的最佳尝试是:

template<typename D, D deleter, typename P>
struct Deleter {
void operator()(P* ptr) {
deleter(ptr);
}
};

template<typename D, D deleter, typename P>
std::unique_ptr<P, Deleter<D, deleter, P>> my_make_unique(P* ptr)
{
return std::unique_ptr<P, Deleter<D, deleter, P>>(ptr);
}

在 C++14 中它更简洁:

template<typename D, D deleter, typename P>
auto my_make_unique(P* ptr)
{
struct Deleter {
void operator()(P* ptr) {
deleter(ptr);
}
};
return std::unique_ptr<P, Deleter>(ptr);
}

但是这两种解决方案都需要我在 fclose 本身之前传递 &fclose 的类型作为模板参数:

auto fd = my_make_unique<decltype(&fclose), fclose>(fopen("filename", "r"));

是否有可能在 C++11 中去掉 decltype(&fclose) 模板参数?在 C++14 中呢?

编辑:为什么这个问题不是 RAII and smart pointers in C++ 的重复问题:引用的问题是关于 C++ 中的一般 RAII 技术,std::unique_ptr 可用于此目的的答案之一。我已经熟悉 RAII 模式以及 std::unique_ptr 是一种解决方案,但我关心的是当前的问题,即如何为我在与 C 交互时遇到的这种常见情况构建更易于使用的抽象图书馆。

最佳答案

Is it possible to get rid of decltype(&fclose) template argument in C++11? What about in C++14?

不,直到 C++17 才能摆脱该参数的类型。模板非类型参数需要一个您无法推断的类型——因为它必须是一个模板非类型参数。这是一个问题。

此外,您遇到的问题是未指定获取标准库中函数的地址。标准库总是允许提供额外的重载,例如,所以 &fclose可能无效。唯一真正可移植的方法是提供 lambda 或编写您自己的包装函数:

auto my_fclose_lam = [](std::FILE* f) { std::fclose(f); }
void my_fclose_fun(std::FILE* f) { std::fclose(f); }

对于其中任何一个,C++14 最多可以引入一个宏,如:

#define DECL(v) decltype(v), v
auto fd = my_make_unique<DECL(my_fclose_lam)>(fopen("filename", "r"));

C++17 允许您至少通过 template auto 将您的自定义函数提升为模板参数(尽管还不是 lambda)。 :

template <auto deleter, typename P>
auto my_make_unique(P* ptr)
{
struct Deleter {
void operator()(P* ptr) {
deleter(ptr);
}
};
return std::unique_ptr<P, Deleter>(ptr);
}

my_make_unique<my_fclose_fun>(fopen(...));

C++20 最终将允许您将 lambda 插入其中:

my_make_unique<[](std::FILE* f){ std::fclose(f); }>(fopen(...));

旧的错误答案:

所以你能做的最好的就是引入一个像这样的宏:

#define DECL(v) decltype(v), v
auto fd = my_make_unique<DECL(&fclose)>(fopen("filename", "r"));

您是否认为这是个好主意可能取决于您的同事。


在 C++17 中,使用 template auto , 你可以写成 my_make_unique<fclose> ,这很棒:

template <auto deleter, typename P>
auto my_make_unique(P* ptr)
{
struct Deleter {
void operator()(P* ptr) {
deleter(ptr);
}
};
return std::unique_ptr<P, Deleter>(ptr);
}

关于c++ - 使用普通函数删除器构建 std::unique_ptr 的包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43378260/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com