这是我经常遇到的RAII问题。我想知道是否有人有一个好的解决方案。RAII和推导出的模板参数
开始用你的标准RAII实用类:
class RAIIHelper {
RAIIHelper() {
AcquireAResource();
}
~RAIIHelper() {
ReleaseTheResource();
}
};
现在,由于种种原因,我需要使它成为一个模板。我们还假设其构造函数模板参数类型的参数:
template <typename T>
class RAIIHelper {
RAIIHelper(T arg) {
AcquireAResource();
}
~RAIIHelper() {
ReleaseTheResource();
}
};
现在考虑使用场所:
void func() {
RAIIHelper<SomeType> helper(someObj);
}
这很烦人有写出来SomeType
时,它可以从someObj
推断,所以我写了一个辅助函数来推断类型:
template <typename T>
RAIIHelper<T> makeRAIIHelper(T arg) {
return RAIIHelper<T>(arg);
}
现在我可以用它像这样:
void func() {
auto helper = makeRAIIHelper(someObj);
}
很好,对不对?除了有一个障碍:RAIIHelper
现在需要是可复制或可移动的,而释放资源的析构函数可能会被调用两次:一次为makeRAIIHelper
返回的临时值,一次为调用函数中的局部变量。
实际上,我的编译器执行RVO,析构函数只被调用一次。但是,这不能保证。从这个事实可以看出,如果我试图给RAIIHelper
一个= delete
'd移动构造函数,代码不再编译。
我可以向RAIIHelper添加额外的状态,以便它知道在移动之后不会调用ReleaseTheResource()
,但这是在添加makeRAIIHelper()
以获得类型扣除之前不必要的额外工作。
有没有一种方法可以得到类型扣除,而不必为RAIIHelper
增加额外的状态?
在旁边,看起来你正在重新创造'unique_ptr',你确定绝对没有天生的'SomeType'类型的哨兵对象吗? – Deduplicator
你可以使用'unique_ptr'。 –
编写适当的移动构造函数并禁用复制构造函数。这应该不成问题。 –