【发布时间】:2015-07-17 15:30:40
【问题描述】:
我正在学习 OpenGL 作为一项练习,并希望推出我自己的数学库,以便使用 C++11 模板轻松进行编程。此问题的解决方案不应调用运行时多态性。
基本的想法是我想要这样的东西(注意这显然不是有效的 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 == 2、n == 3 和 n == 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();
当我实例化 Vector<float, 3> 时,g++ 抱怨 enable_if 没有用于 2 和 4 的 ::type 类型定义。
此时我使用std::array<T, n> 来保存我的值,但我意识到这并没有真正起作用。这是否意味着我的值实际上并不在类中,而是保存在其他地方,因此传递类的数组就像传递std::array<T, n> 的数组,而不是Vec3<T> 的数组?
我目前感兴趣的领域是使用std::tuple<class... Types>,因为它们将值直接存储在类中。这个想法有几个问题:
- 我想将元组的类型限制为只有一种类型,以便我的 Vector 是同质的。
- 我希望能够获得元组的大小而不将其存储在我的类中。
- 我仍然需要以某种方式实现
operator Vec3<T>()和朋友。 - 我不知道
sizeof(tuple<float, float, float>) == sizeof(Vec3<float>)是否有任何保证我可以安全地将tuple<float, float, float>转换为Vec3<float>的内存布局。例如,我听说 g++ 的 stdlib 在类中以相反的顺序存储元组值。
【问题讨论】:
-
这听起来很有趣!虽然,我可能误读了您的实际问题 - 您似乎在问
std::array的值存储在哪里。这是您正在寻找答案的问题吗? -
是的,事实证明这个问题的答案可以解决这个问题!请参阅下面我对 Angew 的评论。
标签: c++ templates c++11 reflection template-meta-programming