我想为 OpenGL 对象(纹理、帧缓冲区等)编写一个简单的 RAII 包装器,我注意到所有glGen*
和glDelete*
函数共享相同的签名,所以我的第一次尝试是这样的:
typedef void (__stdcall *GLGenFunction)(GLsizei, GLuint *);
typedef void (__stdcall *GLDelFunction)(GLsizei, const GLuint *);
template <GLGenFunction glGenFunction, GLDelFunction glDelFunction>
class GLObject
{
GLuint m_name;
public:
GLObject()
{
glGenFunction(1, &m_name);
}
~GLObject()
{
glDelFunction(1, &m_name);
}
GLuint getName() {return m_name;}
};
typedef GLObject<glGenTextures, glDeleteTextures> GLTexture;
它适用于纹理,但不适用于帧缓冲区:glGenFramebuffers
并且glDeleteFramebuffers
函数地址在编译时是未知的,并且不能用作模板参数。所以我做了第二个版本:
class GLObjectBase
{
GLuint m_name;
GLDelFunction m_delFunction;
public:
GLObjectBase(GLGenFunction genFunc, GLDelFunction delFunction)
: m_delFunction(delFunction)
{
genFunc(1, &m_name);
}
GLuint getName()
{
return m_name;
}
protected:
~GLObjectBase()
{
m_delFunction(1, &m_name);
}
};
class GLFrameBuffer : public GLObjectBase
{
public:
GLFrameBuffer() : GLObjectBase(glGenFramebuffers, glDeleteFramebuffers) {}
};
但我不喜欢它,因为我必须在每个实例中存储在运行时不会更改的 del 函数指针。
如何制作仅在每个实例中存储对象名称的包装类,而无需创建一堆几乎复制粘贴的类?
我可以做这样的事情:
template <int N>
class GLObject2
{
GLuint m_name;
static GLDelFunction glDelFunction;
public:
GLObject2(GLGenFunction genFunction, GLDelFunction delFunc)
{
genFunction(1, &m_name);
if ( glDelFunction == nullptr )
glDelFunction = delFunc;
ASSERT(glDelFunction == delFunc);
}
GLuint getName() {return m_name;}
protected:
~GLObject2()
{
glDelFunction(1, &m_name);
}
};
template <int N>
GLDelFunction GLObject2<N>::glDelFunction = nullptr;
class GLTexture: public GLObject2<1>
{
public:
GLTexture(): GLObject2<1>(glGenTextures, glDeleteTextures) {}
};
class GLRenderBuffer: public GLObject2<2>
{
public:
GLRenderBuffer(): GLObject2<2>(glGenRenderbuffers, glDeleteRenderbuffers) {}
};
谁能提出更优雅的解决方案?