将模板化的类存储到向量

时间:2015-11-05 22:10:10

标签: c++ templates vector boost unions

我基本上试图将模板化的类存储在单个std :: vector中。我目前使用的解决方案是一个包含类型的匿名联合的结构:

struct SurfaceUnion
{
    enum { INT, FLOAT }Tag;
    union
    {
        GLSurface<int>*   iGLSurface;
        GLSurface<float>* fGLSurface;
    };
};

std::vector<SurfaceUnion*> vglSurfaces;

问题在于,为了解析我需要的GLSurface,我必须做这样的事情:

for (unsigned int i = 0; i < vglSurfaces.size(); ++i)
    {
        switch (vglSurfaces[i]->Tag)
        {
        case SurfaceUnion::INT:
        {
            if (vglSurfaces[i]->iGLSurface->bIsActive && a_Camera.GetWorldSpace() == vglSurfaces[i]->iGLSurface->uiWorldSpace)
            {
                DrawSurface(*vglSurfaces[i]->iGLSurface, a_Camera);
            }
            break;
        }
        case SurfaceUnion::FLOAT:
        {
            if (vglSurfaces[i]->fGLSurface->bIsActive && a_Camera.GetWorldSpace() == vglSurfaces[i]->fGLSurface->uiWorldSpace)
            {
                DrawSurface(*vglSurfaces[i]->fGLSurface, a_Camera);
            }
            break;
        }
        }
    }

然后我终于可以直接与GLSurface交互,并且不会使用复制粘贴代码

template <typename T, typename U>
void DrawSurface(const GLSurface<T>& ac_glSurface, const Camera<U>& a_Camera)
{
    glPushMatrix(); // Save the current matrix.

    glTranslatef(                                                                   // Move the image back to its original position
        ac_glSurface.Pos.X + (ac_glSurface.Center.X - ac_glSurface.OffsetD.W / 2),
        ac_glSurface.Pos.Y + (ac_glSurface.Center.Y - ac_glSurface.OffsetD.H / 2),
        0.0f); 
    glScalef(ac_glSurface.Scale.W, ac_glSurface.Scale.H, 0.0f);                     // Scale the image
    glRotatef(ac_glSurface.Rotation, 0.0f, 0.0f, 1.0f);                             // Rotate the image
    glTranslatef(                                                                   // Move the image to (0,0) on the screen
        -ac_glSurface.Pos.X - (ac_glSurface.Center.X - ac_glSurface.OffsetD.W / 2),
        -ac_glSurface.Pos.Y - (ac_glSurface.Center.Y - ac_glSurface.OffsetD.H / 2), 0.0f);

    DrawSurface(ac_glSurface);

    glPopMatrix(); // Reset the current matrix to the one that was saved.
}
template <typename T>
void DrawSurface(const GLSurface<T>& ac_glSurface)
{
    // Drawing the surface using glDrawArrays is here
}

我也有一个相机!每次我需要对Camera或GLSurface做一些事情时,这都是太多的解析。这两个实现组合在一起完全消除了我试图创建的代码中的真正通用性。现在你只能有一个int和float类型。要添加任何其他内容,我必须重写大部分代码,现在解析一个额外的类型。更不用说这是一个.lib的一部分,所以如果将来有一个是必需的,如果不首先重新编译.lib就无法添加它。此外,还有一个电话:

template <typename T>
void DeleteSurface(GLSurface<T>* a_pglSurface)
{
    for (int i = 0; i < vglSurfaces.size(); ++i)
    {
        switch (vglSurfaces[i]->Tag)
        {
        case SurfaceUnion::INT:
        {
            if (vglSurfaces[i]->iGLSurface == a_pglSurface)
            {
                auto DeleteSurface = vglSurfaces[i]->iGLSurface;
                vglSurfaces.erase(vglSurfaces.begin() + i);
                glDeleteTextures(1, &DeleteSurface->Surface);
                delete DeleteSurface;
            }

            break;
        }
        case SurfaceUnion::FLOAT: 
        {
            // Will throw an error if uncommented
            /*if (vglSurfaces[i]->fGLSurface == a_pglSurface)
            {
                auto DeleteSurface = vglSurfaces[i]->fGLSurface;
                vglSurfaces.erase(vglSurfaces.begin() + i);
                glDeleteTextures(1, &DeleteSurface->Surface);
            }

            break;*/
        }
        }
    }
}

由于模板化函数的工作方式,因此无法实现。我需要像过去那样完成这两个函数,并在解析正确的类型后调用另一个函数。

那么,有没有更好的方法来使用当前的实现?因为我可以解析连接到&#39;标签的未知数量的类型。列举?还是完全有另一个实现?

我知道&#39;提升&#39;图书馆,但这远远不是轻量级的补充,它似乎并不是我首先要寻找的东西。我需要直接修改GLSurface的值,并且不能真正只是在访问者函数之后调用访问者函数。我有20个访问者函数,我对当前实现不满意的原因是它在解析后丢失了泛型和冗余函数调用。我基本上拥有和现在一样的东西,但是依赖包括文件夹

我也知道多态,但我不认为有一个基类会有所帮助,因为我需要查看基类不允许我这样做的不同类型的成员变量。

非常感谢任何帮助,因为我已经坚持使用这段可怕的代码了。我已写了很长时间。

1 个答案:

答案 0 :(得分:0)

您无法存储不同的类型。

如果您的类共享一个公共库,可以通过多态引用(std :: reference_wrapper)或(智能)指针存储动态实例。

否则你应该使用静态多态。例如,您可以查看boost::variant<GLSurface<float>, GLSurface<int>>

为了统一操作这些,你最终会做一些静态和运行时多态之间的混合:类型擦除。

使用类型擦除技术,您基本上将(不相关的)类型置于共享的 ad-hoc接口下。