I've written a RAII wrapper for C function pairs which initialize and release resources and it serves me well for most cases.
#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");
}
However, say when a function returns void
like Enter/LeaveCriticalSection
I'm not sure how to go about and do it in this class. Should I specialize the class for SuccessValueType = void
case? Or something with default template parameter should do?
SuccessValueType
andsuccessValue
as class template parameters? couldn't they be parameters of the constructor? then you could create two separate constructors... just thinking aloud – EmmieemmitGL_TRUE
should be enough, its type should be deduced so you won't have to specify it – Emmieemmit