C++ 在构造函数上联合使用已删除函数初始化

C++ 在构造函数上联合使用已删除函数初始化,c++,constructor,copy-constructor,default-constructor,default-copy-constructor,C++,Constructor,Copy Constructor,Default Constructor,Default Copy Constructor,我试图创建一个4*4矩阵的类,它是由16个浮点组成的数组构建的,但我还想将它表示为一个4个vec4的数组(对于每列)。 问题是它无法编译,无论我在哪里调用mat4的构造函数都会出现错误。 我的mat4.h: struct mat4 { union { float elements[4 * 4]; // column major ordering, index = row + col * 4 vec4 columns[4]; };

我试图创建一个4*4矩阵的类,它是由16个浮点组成的数组构建的,但我还想将它表示为一个4个vec4的数组(对于每列)。 问题是它无法编译,无论我在哪里调用mat4的构造函数都会出现错误。
我的mat4.h:

struct mat4 {

    union
    {
        float elements[4 * 4]; // column major ordering, index = row + col * 4
        vec4 columns[4];
    };

    mat4();
    mat4(float diagonal);

    mat4& mul(const mat4& other); //TODO: maybe return mat4
   // vec4 getColumn(int colIndex);
    static mat4 identity(); // construct and return an identity matrix
    static mat4 orthographic(float left, float right, float bottom, float top, float near, float far); // boundaries (clipping planes)
    static mat4 perspective(float fov, float aspectRatio, float near, float far);
    static mat4 translation(const vec3& translation);
    static mat4 scale(const vec3 &scale);
    static mat4 rotation(float angle, const vec3 & axis);
    friend mat4 operator*(mat4 left, const mat4 & right);
    mat4& operator*=(const mat4 &other); //TODO: check that it fits with the vectors
    friend std::ostream &operator<<(std::ostream &stream, const mat4 &m);
};

如何修复此问题?

vec4
声明了一个复制构造函数,因此没有为其类生成隐式移动构造函数。由于工会内部有一个
vec4
数组,其移动构造函数将被删除,因为无法从中移动
vec4
。此外,由于
vec4
有一个用户提供的复制构造函数,因此它被认为是非常重要的,因此工会的复制构造函数也被删除。由于该联合体是
mat4
的成员(并且该联合体有一个已删除的复制和移动构造函数)
mat4
的复制和移动构造函数也被删除

删除的函数仍然在重载解析中发挥作用,因此选择删除的移动构造函数,因为您正在从临时函数初始化返回值。要解决此问题,请在
vec4
中声明一个默认移动构造函数:

struct vec4 {
    // ...
    vec4(vec4&&) = default;
    // ...
};
以及
mat4
中的复制构造函数:

mat4(mat4 const&) {}

如果您有任何需要复制的成员,您必须在确认后手动复制。

0x499602D2的回答解释了您的错误并回答了您提出的特定问题。但我认为用两种可能的方式存储矩阵数据至少是一种奇怪的设计。而且您的实现与它不一致,因为在
mat4&mat4::mul(const mat4&other)
(和其他方法)中,您只使用联合体的
元素

我想你应该考虑什么:

  • 用一个简单的
    浮点元素[4*4]替换并集
  • 添加一个构造函数,该构造函数使用4个
    vec4
    参数,并将值存储到
    元素
    数组中
  • 添加const方法以从矩阵中提取向量
因为定义一个内部实现和任意多个外部表示形式更为常见


它不会直接回答您的问题(@0x499602D2已经回答了),但如果您遵循此建议,问题将消失,因此此答案…

对于新手的问题,复制构造函数和移动构造函数之间的区别是什么?我来自Java背景,不知道移动构造函数是什么…@shoham您的问题的解决方案是在
vec4
中声明移动构造函数,请参见我的编辑。我现在这样做了,似乎没有帮助,但如果我也对mat4做同样的操作:
mat4(mat4&&)=default我只剩下一个错误,我将编辑我的答案,以便更容易看到。@shoham对更改表示抱歉。您的复制构造函数需要是
mat4(mat4 const&){}
。如果你有任何需要复制的成员,你必须手动复制。好的,现在可以了,但是你能详细说明一下这些默认设置吗?为什么我需要声明一个新的空拷贝构造函数?如果出于某种原因我想搬家怎么办?你的建议背后的逻辑是什么?这是因为我在vec4中有一个复制构造函数吗?如果是这样,为什么在mat4中有一个空的,或者我可以把东西放进去?
/*     vec4::vec4() {
            w = 0;
            x = 0;
            y = 0;
            z = 0;
        }
*/
        vec4::vec4(float w, float x, float y, float z) {
            this->w = w;
            this->x = x;
            this->y = y;
            this->z = z;
        }

        vec4::vec4(const vec4 &v) {
            this->w = v.w;
            this->x = v.x;
            this->y = v.y;
            this->z = v.z;
        }

        vec4 vec4::add(const vec4 &other) {
            this->w += other.w;
            this->x += other.x;
            this->y += other.y;
            this->z += other.z;
            return *this;
        }

        vec4 vec4::add(float w, float x, float y, float z) {
            this->w += w;
            this->x += x;
            this->y += y;
            this->z += z;
            return *this;
        }

        vec4 vec4::sub(const vec4 &other) {
            this->w -= other.w;
            this->x -= other.x;
            this->y -= other.y;
            this->z -= other.z;
            return *this;
        }

        vec4 vec4::sub(float w, float x, float y, float z) {
            this->w -= w;
            this->x -= x;
            this->y -= y;
            this->z -= z;
            return *this;
        }

        vec4 vec4::mul(const vec4 &other) {
            this->w *= other.w;
            this->x *= other.x;
            this->y *= other.y;
            this->z *= other.z;
            return *this;
        }

        vec4 vec4::mul(float w, float x, float y, float z) {
            this->w *= w;
            this->x *= x;
            this->y *= y;
            this->z *= z;
            return *this;
        }

        vec4 vec4::div(const vec4 &other) {
            this->w /= other.w;
            this->x /= other.x;
            this->y /= other.y;
            this->z /= other.z;
            return *this;
        }

        vec4 vec4::div(float w, float x, float y, float z) {
            this->w /= w;
            this->x /= x;
            this->y /= y;
            this->z /= z;
            return *this;
        }

        std::ostream &operator<<(std::ostream &stream, const vec4 &vector) {
            stream << "vec4: (" << vector.w << ", " << vector.x << ", " << vector.y << ", " << vector.z << ")";
            return stream;
        }

        vec4 operator+(vec4 left, const vec4 &right) {
            return left.add(right);
        }

        vec4 operator-(vec4 left, const vec4 &right) {
            return left.sub(right);
        }

        vec4 operator*(vec4 left, const vec4 &right) {
            return left.mul(right);
        }

        vec4 operator/(vec4 left, const vec4 &right) {
            return left.div(right);
        }

        vec4 vec4::operator+=(const vec4 &other) {
            return add(other);
        }

        vec4 vec4::operator-=(const vec4 &other) {
            return sub(other);

        }

        vec4 vec4::operator*=(const vec4 &other) {
            return mul(other);

        }

        vec4 vec4::operator/=(const vec4 &other) {
            return div(other);

        }

        bool vec4::operator==(const vec4 &other) {
            return (this->w == other.w && this->x == other.x && this->y == other.y && this->z == other.z);
        }

        bool vec4::operator!=(const vec4 &other) {
            return !(*this == other);
        }
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::identity()’:
.../src/math/mat4.cpp:36:29: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’
             return mat4(1.0f);
                             ^
In file included from .../src/math/mat4.cpp:5:0:
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(engine::math::mat4&&)’ is implicitly deleted because the default definition would be ill-formed:
         struct mat4 {
                ^
.../src/math/mat4.h:16:31: error: union member ‘engine::math::mat4::<anonymous union>::columns’ with non-trivial ‘engine::math::vec4::vec4(const engine::math::vec4&)’
                 vec4 columns[4];
                               ^
.../src/math/mat4.cpp: In function ‘engine::math::mat4 engine::math::operator*(engine::math::mat4, const engine::math::mat4&)’:
.../src/math/mat4.cpp:40:34: error: use of deleted function ‘engine::math::mat4::mat4(const engine::math::mat4&)’
             return left.mul(right);
                                  ^
In file included from .../src/math/mat4.cpp:5:0:
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(const engine::math::mat4&)’ is implicitly deleted because the default definition would be ill-formed:
         struct mat4 {
                ^
.../src/math/mat4.h:16:31: error: union member ‘engine::math::mat4::<anonymous union>::columns’ with non-trivial ‘engine::math::vec4::vec4(const engine::math::vec4&)’
                 vec4 columns[4];
                               ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::orthographic(float, float, float, float, float, float)’:
.../src/math/mat4.cpp:56:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’
             return result;
                    ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::perspective(float, float, float, float)’:
.../src/math/mat4.cpp:69:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’
             return result;
                    ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::translation(const engine::math::vec3&)’:
.../src/math/mat4.cpp:77:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’
             return result;                                  //                             0 0 0 1
                    ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::scale(const engine::math::vec3&)’:
.../src/math/mat4.cpp:85:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’
             return result;                            //                             0 0 0 1
                    ^
.../src/math/mat4.cpp: In static member function ‘static engine::math::mat4 engine::math::mat4::rotation(float, const engine::math::vec3&)’:
.../src/math/mat4.cpp:105:20: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’
             return result;
                    ^
CMakeFiles/GameEngine.dir/build.make:169: recipe for target 'CMakeFiles/GameEngine.dir/src/math/mat4.cpp.o' failed
make[3]: *** [CMakeFiles/GameEngine.dir/src/math/mat4.cpp.o] Error 1
make[3]: *** Waiting for unfinished jobs....
.../main.cpp: In function ‘int main(int, char**)’:
.../main.cpp:19:50: error: use of deleted function ‘engine::math::mat4::mat4(engine::math::mat4&&)’
     mat4 position = mat4::translation(vec3(2,3,4));
                                                  ^
In file included from .../src/math/math.h:8:0,
                 from .../main.cpp:4:
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(engine::math::mat4&&)’ is implicitly deleted because the default definition would be ill-formed:
         struct mat4 {
                ^
.../src/math/mat4.h:16:31: error: union member ‘engine::math::mat4::<anonymous union>::columns’ with non-trivial ‘engine::math::vec4::vec4(const engine::math::vec4&)’
                 vec4 columns[4];
                               ^
.../src/math/mat4.cpp: In function ‘engine::math::mat4 engine::math::operator*(engine::math::mat4, const engine::math::mat4&)’:
.../src/math/mat4.cpp:39:34: error: use of deleted function ‘engine::math::mat4::mat4(const engine::math::mat4&)’
             return left.mul(right);
                                  ^
In file included from .../src/math/mat4.cpp:5:0:
.../src/math/mat4.h:11:16: note: ‘engine::math::mat4::mat4(const engine::math::mat4&)’ is implicitly declared as deleted because ‘engine::math::mat4’ declares a move constructor or move assignment operator
         struct mat4 {
                ^
struct vec4 {
    // ...
    vec4(vec4&&) = default;
    // ...
};
mat4(mat4 const&) {}