2015-11-05 104 views
0

我基本上试图将模板类存储在单个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;*/ 
     } 
     } 
    } 
} 

由于模板化函数的工作方式,所以不可行。我需要像过去那样完成这2个函数,并且在解析正确的类型之后再调用另一个函数。

那么,有没有更好的方式来使用当前的实现?正如在我可以解析通过连接到'标记'枚举的未知数量的类型?还是完全有另一种实现?

我知道'增强'库,但是这远不是轻量级的增加,它似乎并不是我一直在寻找的东西。我需要直接修改GLSurface的值,并且在访问者函数之后不能真正调用访问者函数。我有20个访问者函数,并且我对目前的实现不满意的原因是它在解析后失去了通用性和多余的函数调用。我基本上有同样的事情,我现在有,但有一个巨大的依赖性包括文件夹

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

任何帮助是非常赞赏,因为我一直坚持这个可怕的代码,我已经很长一段时间写的。

+0

我没有阅读所有文章,但是'std :: vector >'有什么问题? – Jepessen

+0

同样在这里。通读并无法弄清楚有两个不同的实例是什么点。 – SergeyA

+0

这是所有名字空间的内部。即使不是这样,关键是将GLSurface 和GLSurface 放在同一个向量中......除非T被定义为类型,否则不能只说std :: vector <'MyClass'>我知道,这种类型是绝对的,这意味着它不能从int变为float。这是除非我根本不了解模板。 – bennybroseph

回答

0

您不能存储不同的类型。

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

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

要对这些进行统一的操作,您最终需要完成静态和运行时多态之间的混合操作:type erase。

使用类型擦除技术,您基本上会在共享的特设接口下带来(无关的)类型。

+0

我抬头'类型擦除'。我发现的例子是这样的: http://www.cplusplus.com/articles/oz18T05o/ 该示例在结构中没有任何成员变量。我允许成员变量?我可以通过“getter”函数访问它们吗?无法以某种方式直接检索值,输入擦除对我来说不是一个可行的解决方案。我对这个概念很感兴趣,并且想知道它的工作方式与我在示例中看到的不同。 – bennybroseph

+0

看起来像一个公平的例子。 'std :: function <>'也可以。 Boost Type Erase是一个完整的库。 – sehe

+0

如果可能的话,我想尽量避免使用增强功能,除非将其安装在家庭/学校使用的每台计算机上,否则会造成太大的麻烦。 std :: function <>看着我的头,但我可以问我的教授。你能再次看看我的评论吗?输入链接时,我不小心碰到了回车,并且您非常快速地回答!谢谢 – bennybroseph