如果你不想自己动手写,你可以检查一些库的建议上:
C++ Vector Math and OpenGL compatable
如果你使用一个特定的编译器,你可以使用非标准方法,如包装信息或无名结构(Visual Studio中):
union Vec3
{
struct {double x, y, z;};
double v[3];
};
在另一方面,铸造几个成员变量的阵列似乎危险的,因为编译器可能改变类布局。
所以逻辑解决方案似乎有一个数组,并使用方法来访问该数组。例如:
template<size_t D>
class Vec
{
private:
float data[D];
public: // Constants
static const size_t num_coords = D;
public: // Coordinate Accessors
float& x() { return data[0]; }
const float& x() const { return data[0]; }
float& y() { static_assert(D>1, "Invalid y()"); return data[1]; }
const float& y() const { static_assert(D>1, "Invalid y()"); return data[1]; }
float& z() { static_assert(D>2, "Invalid z()"); return data[2]; }
const float& z() const { static_assert(D>2, "Invalid z()"); return data[2]; }
public: // Vector accessors
float& operator[](size_t index) {return data[index];}
const float& operator[](size_t index) const {return data[index];}
public: // Constructor
Vec() {
memset(data, 0, sizeof(data));
}
public: // Explicit conversion
template<size_t D2>
explicit Vec(const Vec<D2> &other) {
memset(data, 0, sizeof(data));
memcpy(data, other.data, std::min(D, D2));
}
};
使用上述类,可以使用[]操作者访问构件阵列,坐标使用存取方法X()中,y(),Z()。使用显式的转换构造函数可以防止切片。它使用static_assert禁用较低维度的访问器。如果您不使用C++ 11,则可以使用Boost.StaticAssert
您也可以使用模板化方法。您可以使用作为以便将它们扩展到N维或使用递归调用。例如,为了计算平方和:
template<size_t D>
struct Detail
{
template<size_t C>
static float sqr_sum(const Vec<D> &v) {
return v[C]*v[C] + sqr_sum<C-1>(v);
}
template<>
static float sqr_sum<0>(const Vec<D> &v) {
return v[0]*v[0];
}
};
template<size_t D>
float sqr_sum(const Vec<D> &v) {
return Detail<D>::sqr_sum<D-1>(v);
}
上面的代码可用于:
int main()
{
Vec<3> a;
a.x() = 2;
a.y() = 3;
std::cout << a[0] << " " << a[1] << std::endl;
std::cout << sqr_sum(a) << std::endl;;
return 0;
}
为了防止模板膨胀,可能会在一段cpp的代码你的模板方法和实例他们为D = 1,2,3,4 4.
如果你不介意一些编译器的特殊性,你可以使用[这个问题]中显示的方法之一(http://stackoverflow.com/questions/1537964/visual-c-equivalent-of-gccs-attribute-packed)来确保在不使用数组的情况下打包数据成员。 – 2011-12-16 13:32:13