这是我经常遇到的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 move构造函数,则该代码将不再编译。

我可以向RAIIHelper添加其他状态,以便它知道从其移出后不调用ReleaseTheResource(),但是在我添加makeRAIIHelper()以获得类型推论之前,这是不必要的额外工作。

有没有一种方法可以获取类型推断,而不必在RAIIHelper中添加额外的状态?

最佳答案

有一个非常简单的解决方案:使用对临时对象的引用,而不是将其复制到局部变量中。

void func()
{
    auto&& helper = makeRAIIHelper(someObj);
}

关于c++ - RAII和推导的模板参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24743328/

10-11 22:50