lve*_*lla 5 c++ templates c++11 c++14
我试图实现一个std::unique_ptr我可以这样使用的工厂:
auto fd = my_make_unique<fclose>(fopen("filename", "r"));
Run Code Online (Sandbox Code Playgroud)
即,将删除函数作为模板参数传递.
我在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);
}
Run Code Online (Sandbox Code Playgroud)
在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);
}
Run Code Online (Sandbox Code Playgroud)
但是这两种解决方案都要求我将自己&fclose之前的类型fclose作为模板参数传递:
auto fd = my_make_unique<decltype(&fclose), fclose>(fopen("filename", "r"));
Run Code Online (Sandbox Code Playgroud)
是否有可能摆脱decltype(&fclose)C++ 11中的模板参数?在C++ 14中怎么样?
编辑:为什么这个问题不是CII中RAII和智能指针的重复:引用的问题是关于C++中的一般RAII技术,以及std::unique_ptr可用于此目的的答案之一.我已经熟悉RAII模式以及如何std::unique_ptr解决方案,但我关注如何构建一个更容易使用的抽象来解决我在与C库交互时遇到的这种常见情况.
是否可以摆脱
decltype(&fclose)C++11 中的模板参数?在 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); }
Run Code Online (Sandbox Code Playgroud)
使用其中任何一个,最多使用 C++14,您可以引入一个宏,例如:
#define DECL(v) decltype(v), v
auto fd = my_make_unique<DECL(my_fclose_lam)>(fopen("filename", "r"));
Run Code Online (Sandbox Code Playgroud)
C++17 允许您至少通过以下方式将自定义函数提升为模板参数(尽管还不是 lambda)template auto:
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(...));
Run Code Online (Sandbox Code Playgroud)
C++20 最终将允许您将 lambda 插入其中:
my_make_unique<[](std::FILE* f){ std::fclose(f); }>(fopen(...));
Run Code Online (Sandbox Code Playgroud)
旧的错误答案:
所以你能做的最好的事情就是引入一个宏,比如:
#define DECL(v) decltype(v), v
auto fd = my_make_unique<DECL(&fclose)>(fopen("filename", "r"));
Run Code Online (Sandbox Code Playgroud)
您是否认为这是一个好主意可能取决于您的同事。
在 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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
747 次 |
| 最近记录: |