Если вы не хотите писать это самостоятельно, вы можете проверить некоторые из библиотек, предлагаемых для:
C ++ Vector Math и OpenGL, совместимые
Если вы используетеВ одном конкретном компиляторе вы можете использовать нестандартные методы, такие как упаковка информации или безымянные структуры (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.