我为一对初始化和释放资源的 C 函数编写了一个 RAII 包装器,它在大多数情况下都能很好地服务于我。
#include <GL/glfw.h>
#include <string>
#include <functional>
#include <stdexcept>
template <typename UninitFuncType,
typename SuccessValueType,
SuccessValueType successValue>
class RAIIWrapper
{
public:
template <typename InitFuncType, typename... Args>
RAIIWrapper(InitFuncType initializer,
UninitFuncType uninitializer,
const std::string &errorString,
const Args&... args) :
uninit_func(uninitializer)
{
if (successValue != initializer(args...))
throw std::runtime_error(errorString);
initialized = true;
}
bool isInitialized() const
{
return initalized;
}
~RAIIWrapper()
{
if (initalized)
uninit_func();
}
// non-copyable
RAIIWrapper(const RAIIWrapper &) = delete;
RAIIWrapper& operator=(const RAIIWrapper &) = delete;
private:
bool initalized = false;
std::function<UninitFuncType> uninit_func;
};
using GLFWSystem = RAIIWrapper<decltype(glfwTerminate), decltype(GL_TRUE), GL_TRUE>;
using GLFWWindow = RAIIWrapper<decltype(glfwCloseWindow), decltype(GL_TRUE), GL_TRUE>;
int main()
{
GLFWSystem glfw(glfwInit,
glfwTerminate,
"Failed to initialize GLFW");
}
不过,当一个函数返回void
时,比如Enter/LeaveCriticalSection
,我不确定该如何在这个类中实现。 我应该为SuccessValueType = void
的情况专门化该类吗? 还是使用默认模板参数做些什么?
SuccessValueType
和successValue
作为类模板参数吗?它们不能是构造函数的参数吗?这样,你就可以创建两个单独的构造函数...只是随口一想。 - Andy ProwlGL_TRUE
应该足够了,它的类型应该被推断出来,所以您不必指定它。 - Andy Prowl