如果你不想自己動手寫,你可以檢查一些庫的建議上:
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