Vec<int,4> v(); v[0] = -2; // <- set first value to -2 v[1] = 1; // <- set second value to 1 ....
但这是我的问题:我如何为v [0],v [1],v [2],v [3]?创建别名.我想将前4个值定义为v.x,v.y,v.z,v.w:
Vec<int,4> v(); v.x = -2; // <- set first value to -2 v.y = 1; // <- set second value to 1 v.z = 4; // <- set third value to 4 v.w = 2; // <- set fourth value to 2
我应该能够分配和读取值,我不希望它们看起来像一个函数,所以访问第一个值,如:
Vec<int,4> v(); v.x() = -2; // <- set first value to -2
没有好处.最重要的是,矢量类是模板化的,x应仅为尺寸> = 1定义,而y仅限于尺寸> = 2 ……等等…我如何实现这一目标?
编辑:Vector类与std :: vector无关,它是一个类似于数组的数学向量,因为它具有固定的大小,仅用于数学运算. (将Vector重命名为Vec).
我尝试过的:
矩阵类:
template <typename T,size_t ROWS,size_t COLS> class Matrix { public: T& operator[] (size_t idx) {return m_matrix[idx];} T operator[] (size_t idx) const {return m_matrix[idx];} private: m_matrix[ROWS * COLS] };
矢量类:
template <typename T,size_t N> class Vec: public Matrix<T,1,N>{ public: T& x() {return (*this)[0];} T x() const {return (*this)[0];} T& y() {return (*this)[1];} T y() const {return (*this)[1];} T& z() {return (*this)[2];} T z() const {return (*this)[2];} T& w() {return (*this)[3];} T w() const {return (*this)[3];} };
这很有效,如果没有为这个维度定义,我很容易使用enable_if来删除函数,但这在语法上并不令人满意.我试过使用引用:
template <typename T,N,1>{ public: T& x = (*this)[0]; T& y = (*this)[1]; T& z = (*this)[2]; T& w = (*this)[3]; };
但这不起作用,它不会给我一个错误,但它也没有正确设置值,当我在设置它们未定义后访问它们.
编辑nr 2:可能只存在一个更简单的解决方案,当我最后一次使用Visual Studio社区2015的默认编译器编译引用时,它就可以工作了.但是当我使用GNU GCC编译器在Code :: Blocks中编译它时,它却没有.标准说什么?我的解决方案是否允许使用引用,哪个编译器是错的?
解决方法
// General case uses an array template<class T,std::size_t N> class VectorData { private: T m_data[N]; public: T& operator[](int i) { return m_data[i]; } const T& operator[](int i) const { return m_data[i]; } }; // Specializations for varIoUs N (4 shown here) template<class T> class VectorData<T,4> { public: T x,y,z,w; T& operator[](int i) { return (&x)[i]; } // WARNING,see note below const T& operator[](int i) const { return (&x)[i]; } }; template<class T,std::size_t N> struct Vector : public VectorData<T,N> { // your other Vector stuff here };
注意:正如下面正确指出的一个评论者所说,这假设数组元素在内存中的布局与变量列表完全相同(iow,T [4]和struct {T x,w;}与布局兼容)& x [i]部分可以工作.标准不保证这一点,因此该代码将产生未定义的行为.在实践中,这很好,这样做是更高效的方式.如果您需要便携式,标准兼容的实现,您可以选择使用VectorData :: operator []中的开关,如另一个答案所示.生成的代码差异可以看到here.
如果你真的需要Vector来自Matrix,那么这样的东西仍然是可能的.一般的想法只是你解耦存储和功能.您可以创建一些具有所有功能的通用Matrix类,该类具有其存储的额外模板参数.然后,Vector可以提供自己的存储类型.
就像是:
// Generic matrix storage template<class T,std::size_t N> class MatrixData { private: T m_data[N]; public: T& operator[](int i) { return m_data[i]; } const T& operator[](int i) const { return m_data[i]; } }; // Generic matrix class template<class T,std::size_t ROWS,std::size_t COLS,class Storage = MatrixData<T,ROWS*COLS>> class Matrix : public Storage { // Matrix functionality here }; // Specialized storage for Vectors,generic version template<class T,std::size_t N> class VectorData : public MatrixData<T,N> { }; // Specialized storage for Vector<T,4> template<class T> class VectorData<T,w; T& operator[](int i) { return (&x)[i]; } const T& operator[](int i) const { return (&x)[i]; } }; template<class T,std::size_t N> struct Vector : public Matrix<T,VectorData<T,N>> { // your other stuff here };