我最近被介绍到这种使用 std::unique_ptr
来实现“通用”RAII 机制的机制:
// main.cpp
#include <memory>
#include <sys/fcntl.h>
#include <unistd.h>
#define RAII_CAT(x) raii ## x
#define RAII_CAT2(x) RAII_CAT(x)
#define RAII_FD(X) \
std::unique_ptr<int, void(*)(int*)> RAII_CAT2(__LINE__){X, [](int* x){ if (-1 != *x) { close(*x); }}}
int main(int argc, char* argv[]) {
{
int fd = open("foo.txt", O_RDONLY);
RAII_FD(&fd);
}
end:
return 0;
}
在上面的代码中,RAII_FD
宏创建一个 std::unique_ptr
对象,其自定义删除器接受一个 int*
——指向文件描述符的指针——并在文件描述符上调用 close()
。
我非常喜欢这种机制,但我有点抱怨自定义删除器需要一个 pointer 作为它的论点:从美学上讲,它感觉有点不尽如人意。
例如。在上面的代码中,自定义删除器是 int close(int)
的一个薄包装器——因此,如果自定义删除器可以采用 int
而不是 int*
就好了……在这种情况下,可能不需要包装器函数根本:也许可以提供指向 int close(int)
本身的函数指针。
即尝试了以下变体,尝试注册一个带有签名 void func(int)
而不是 void func(int*)
:
// main.cpp
#include <memory>
#include <sys/fcntl.h>
#include <unistd.h>
#define RAII_CAT(x) raii ## x
#define RAII_CAT2(x) RAII_CAT(x)
#define RAII_FD(X) \
std::unique_ptr<int, void(*)(int)> RAII_CAT2(__LINE__){X, [](int x){ if (-1 != x) { close(x); }}}
int main(int argc, char* argv[]) {
{
int fd = open("foo.txt", O_RDONLY);
RAII_FD(fd);
}
end:
return 0;
}
...编译错误是 stl 错误的呕吐物,我可能不会 100% 理解,但我认为要点是在各种模板扩展中存在 int*
/int
不匹配。
是否有另一种类似的机制可以通过自定义删除器实现“通用”RAII 机制,其参数不一定需要是指针?
我愿意学习所有可能的解决方案,但在我的目标环境中实际可用的解决方案必须是 C++11 和非 Boost。最可取的是在 STL 原生对象上使用一些类似的“薄包装器”。