将元组转换为模板中的结构

时间:2015-07-17 15:30:40

标签: c++ templates c++11 reflection template-meta-programming

我正在学习OpenGL作为练习,并希望自己编写数学库,以便用C ++ 11模板进行编程。该问题的解决方案不应该调用runtime-polymorphism。

基本思想是我想要这样的东西(请注意,这显然不是有效的C ++代码):

template<class T, int n> //element type is T, size is n
class Vector {
    T v1, v2, ... , vn;
public:
    Vector(T v1, ... , T vn);
    ~Vector() noexcept;
    ...
    // more constructors and stuff here.
}

template<T, n>
Vector<T, n> operator +(Vector<T, n> lhs, Vector<T, n> rhs);

...
// more math functions and operators here...

问题在于,当我们将这些向量作为数组传递给OpenGL函数时,我希望将这些向量转换为常规C结构 。例如,对于n == 3,我想将Vector<T, 3>转换为:

template<class T>
struct Vec3 {
    T v1, v2, v3;
}

这样我就可以打电话了:

Vector<float, 3> vertices[1];
vertices[0] = Vector<float, 3>(1.0f, 1.0f, 1.0f);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

并让它正常工作,就像我使用了Vec3<float>的数组一样。我希望n == 2n == 3n == 4出现此行为。我不想写3个类并为每个类实现数学运算符。

我的第一次尝试尝试将SFINAE与投射操作符一起使用:operator T()

// Inside Vector's declaration...
public:
    operator typename std::enable_if<n == 3, Vec3<T>>::type();

这可能仅适用于n == 3,但我还需要:

    operator typename std::enable_if<n == 2, Vec2<T>>::type();
    operator typename std::enable_if<n == 4, Vec4<T>>::type();

当我实例化enable_if时,g ++抱怨::type没有Vector<float, 3> typedef for 2和4。

此时我使用std::array<T, n>来保持我的价值观,但我意识到这并没有真正起作用。这不意味着我的值实际上并不是在类中,并且保存在其他地方,因此传递类的数组就像是通过std::array<T, n>的数组,而不是Vec3<T>的数组?

我目前感兴趣的领域是使用std::tuple<class... Types>,因为它们直接将值存储在类中。这个想法存在一些问题:

  1. 我想将元组的类型限制为只有一种类型,这样我的Vector就是同质的。
  2. 我希望能够获得元组的大小而不将其存储在我的班级中。
  3. 我仍然需要以某种方式实现operator Vec3<T>()和朋友。
  4. 我不知道sizeof(tuple<float, float, float>) == sizeof(Vec3<float>)或任何关于记忆布局的保证人是否允许我安全地(假设)将tuple<float, float, float>投射到Vec3<float>。我听说g ++的stdlib在类中以相反的顺序存储元组值,例如。

1 个答案:

答案 0 :(得分:4)

std::array<T, n>保证是T[n]上的零开销包装器,所以你可以简单地将它存储在你的类中,并确保没有可能搞乱OpenGL调用的填充。