我最近了解了使用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()
。
我非常喜欢这种机制,但是我有一个小小的抱怨,即定制的deleter需要一个 pointer 作为它的参数:从美学上看,感觉有点不太理想。
例如,在上面的代码中,自定义删除器是int close(int)
上的一个薄 Package 器--因此,如果自定义删除器可以接受int
而不是int*
,那就太好了......在这种情况下,可能根本不需要 Package 器函数:也许可以提供指向X1 M8 N1 X本身的函数指针。
例如,尝试了以下变体,尝试使用签名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原生对象上使用类似的“薄 Package 器”。
1条答案
按热度按时间dohp0rv51#
std::unique_ptr
实际上并不只是对原生原始指针进行操作。它支持满足NullablePointer requirements的所有类型。基本上,该类型在值语义和相等比较方面的行为应该像标量类型一样,并且可以使用nullptr
为空,进入一个不同的空状态,该状态也是值初始化状态。这要求您有一个状态来表示空状态,在您的情况下可以由-1
提供。这样的类型将作为自定义删除器的类型成员
pointer
提供给unique_ptr
:然后您可以使用
实际上元素类型是
int
并不重要。std::unique_ptr<double, Deleter>
也可以工作。但是,你不能用*u
来解引用。如果这是必需的,那么你需要给予pointer
一个operator*
,在这种情况下,元素类型应该匹配它返回的类型。考虑到大量的样板代码和对
pointer
的不寻常的解释,这是否真的有用取决于您。