gpt4 book ai didi

c++ - 编译器在乘以子类型时选择了错误的运算符*

转载 作者:行者123 更新时间:2023-11-30 05:37:11 26 4
gpt4 key购买 nike

我在自己的库中编写了一个通用 Matrix 类,其中包含 +、-、* 等不错的运算符。特别是,它有(函数体并不重要,所以你可以忽略它们,但我稍后仍然会引用它,所以有它很好):

template<typename T, int X, int Y>
Matrix<T,Y,X> operator*(const Matrix<T,Y,X> & left, const Matrix<T,Y,X> & up)
{
Matrix<T,Y,X> result = Matrix<T,Y,X>::Zero;
for (unsigned int j = 0; j<Y; j++)
for (unsigned int i = 0; i<X; i++)
for (unsigned int k = 0; k<X; k++)
result[j][k] += left[j][i] * up[i][k];
return result;
}
template<typename T, int Y, int X, typename U>
Matrix<T,Y,X> operator*(const Matrix<T,Y,X> & left, const U & right)
{
// Expected to handle build-in types
Matrix<T, Y, X> result = Matrix<T, Y, X>::Zero;
for (int j = 0; j < Y; ++j)
for (int i = 0; i < X; ++i)
result[j][i] += left[j][i] * right;
return result;
}

然后我写了Matrix4x4 , Matrix 的子类型专门用于旋转和平移等 3D 变换,因此它具有相关的成员函数。授予,Matrix4x4是一个坏名字,我保证我会解决这个问题。

在代码中的某个时刻使用了 Matrix4x4我用 operator* :

// std::vector<Matrix4x4> mstackvertices({Matrix4x4::Identity});
mstackvertices.push_back(mstackvertices.back() * m_camera.m_projectionmatrix);

在这里m_camera.m_projectionmatrixMatrix4x4也是。

这应该调用第一个 operator* , 但属于第二个,因为 gcc 在第二个重载中给我一个错误,在以下行中:

            result[j][i] += left[j][i] * right;

错误信息:

Matrix.hpp|169|error: no match for ‘operator*’ (operand types are ‘const float’ and ‘const swegl::Matrix4x4’)|
Matrix.hpp|169|note: candidates are:|
...

我的猜测是 Matrix4x4不完全是 Matrix ,但只是一个子类型,一些规则适用,使 gcc 选择不涉及类型转换的最佳重载。

我不确定如何解决这个问题。我考虑了几种解决方案,但似乎都不好:

  • 删除将接收内置类型的运算符,从而迫使编译器选择唯一剩余的重载。这行得通,但迫使我从看似完美运行的库中删除一个功能。
  • 使用组合而不是继承并重载所有相关的 Matrix4x4的运算符 Matrix .
  • 重新实现 operator*Matrix4x4 .会有重复的代码,或者,如果我能设法调用 Matrix::operator* 的正确重载好吧,这仍然很麻烦。
  • 创建 Matrix4x4::operator Matrix<float,4,4>() .它似乎不起作用,但我也可能在那里做错了什么。无论如何,我知道这会创建一个不受欢迎的对象拷贝。

这就是我现在的位置。还有其他想法吗?也许我首先做错了什么?我确定我会从中学到一些东西,因此欢迎任何帮助(:

编辑:

Matrix 的定义和 Matrix4x4正如所问:

template<typename T, int Y, int X>
class Matrix
{
private:
T data[Y][X];
...
};

class Matrix4x4 : public Matrix<float,4,4>
{
...
};

最佳答案

按如下方式使用 Koenig 运算符:

template<class T, int X, int Y>
class Matrix{
// ...
public:
// calculates the return value of `T*U`:
template<class U>
using R=decltype(std::declval<T const&>()*std::declval<U const&>());
// maybe addin a `decay_t` to the above, if required. (But who returns
// a reference from binary `*`?)

// Multiplication by a matrix on the RHS
// The RHS dimension of this matrix, and the LHS dimension
// of the RHS matrix, must match. Accepts matrices with a
// different underlying T.
template<class U, int Z>
Matrix<R<U>,X,Z> operator*(Matrix<U,Y,Z>const& rhs)const;
// you can implement this operator here, or you can do it below
// in the same header file.

// This is the Koenig operator. It is a friend operator that
// is *not* a template, where the left hand side is a scalar of
// type T, and the right hand side is our own type.
friend Matrix<R<T>,X,Y> operator*(
T const& lhs, Matrix const& rhs
){
// implement here
}
};

成员矩阵乘法比非成员更好地处理歧义。友元运算符就是我所说的 Koenig 运算符,必​​须在类中内联实现。您可以调用另一个函数并执行该函数。

您也可以随意使用 sfinae 或标签调度,但上面的内容非常简洁明了。请注意,标量只允许在 lhs 上使用,因为 Matrix * Scalar 是......古怪。 Scalar * Matrix 更常规。

关于c++ - 编译器在乘以子类型时选择了错误的运算符*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33337379/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com