Matrix中的'operator *'没有匹配运算符

时间:2011-12-21 08:40:34

标签: c++ templates casting operators

我有一个矩阵类,如下所示:

template <size_t M, size_t N, typename T>
class Matrix
{
public:
    Matrix<M, N, T> operator +(const Matrix<M, N, T>& B) const;
    template <size_t P> Matrix<M,P,T> operator*(const Matrix<N, P, T>& B) const;
    template <typename T2> operator T2() const;  

private:
  T data[M][N];
};

// ... the body is in header file too  ...//

身体写得很好,一切都运作良好。 当我定义两个矩阵时如下:

Matrix < 10, 10, int> m1;
Matrix < 10, 10, float> m2;

m1 + m2;  // OK
m1 * m2;  // error: no match for 'operator*' in 'm1 * m2'

第一个'+'运算符运行良好,因为已对其执行了隐式转换。 但是对于不同值类型的第二个'*'运算符,会发生错误。

  

错误:'m1 * m2'中的'operator *'不匹配

有什么想法吗?!

更新 所有代码都在头文件中。我没有问题,但对于'*'运算符。

关于'+'运算符你能说什么?我知道关于模板/运算符/转换的一切......但是这个问题就像我的gcc编译器的一个错误!?我写了一个cast-operator,这个运算符在'+'运算符之前调用,但我不知道为什么它不能为'*'运算符执行!

2 个答案:

答案 0 :(得分:6)

问题或多或少是经典的。重载决议开始于 建立可能的功能列表;在这种情况下,函数命名 operator*。为此,它添加了所有operator*函数 范围到列表,它尝试通过实例化所有函数模板 申请类型扣除;如果类型扣除成功,它会添加 将模板实例化到列表中。 (功能模板是 一个功能。函数模板的实例化是a 功能。)

模板类型推导的规则与使用的规则不同 超载分辨率。特别是,只有一小部分 转换被考虑。用户定义的转换运算符不是 考虑。结果是m1 * m2中的类型扣除 operator*失败(因为它需要转换而不是 考虑)。因此,不添加函数模板的实例化 列表,没有其他operator*

更一般地说:你operator T2()不允许类型扣除 即使它被允许;转化次数无限 哪个匹配operator*。事实上,我怀疑你已经做到了 太笼统了;你想要一个operator Matrix<M, N, T2>()。 (不是那个 这在这里会有所帮助,但有些情况可能会消除 多义性。)

您可以通过定义:

来使其工作
template<size_t P, tyepname OtherT>
Matrix<M, P, T> operator*( Matrix<N, P, T> const& rhs ) const;

,然后在运营商*内进行转换。 (我没试过, 我不确定,但我认为你现有的operator*应该是 被认为是“更专业化”,因此在选择时选择 扣除成功。)

话虽如此,我认为你这样做的方法是错误的。 您真的想要m1 * m2m2 * m1的返回类型吗? 不同。对于初学者,我需要客户端代码来制作 转换显式(在当前代码中就是这种情况);如果你这样做 想要支持隐式转换,我想你需要做的 operator*全局,使用某种简单的元编程 确定正确的返回类型(即给定long的矩阵和 unsigned,您可能希望返回类型为unsigned long, 因为这是这些类型的混合型算术给出的 否则),将双方转换为目标类型,并进行算术运算 在上面。很多工作可能不是很重要或者 有用的功能。 (当然,我的意见。如果你的客户真的 想要混合型算术,并且愿意付钱......)

答案 1 :(得分:2)

隐式演员是你的例子中的罪魁祸首(m1 * m1起作用)。虽然我的语言不够完整,无法告诉您具体原因,但我怀疑模板化运算符*方法(未完全指定类型)与必要类型转换的组合具有太多歧义。编译器被告知它可以将矩阵转换为任何类型,并且模板化类型族可以是operator*的有效参数。 在确定从这些方法调用哪个operator*时会遇到问题。将static_cast作为m1 * static_cast< Matrix<10,10,int> >(m2)插入可以确认这一点。

Eigen库是一个相当成熟且非常好的矩阵库,它们也不会进行隐式标量转换。相反,他们使用了一种演员方法:

template <typename Scalar> Matrix<M,N,Scalar> cast() const;

在你的例子中,你写道:

m1.cast<float>() * m2;