我有一个如下所示的矩阵类:
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'
第一个“+”运算符运行良好,因为对其执行了隐式转换。 但是对于不同值类型的第二个 '*' 运算符,会发生错误。
error: no match for 'operator*' in 'm1 * m2'
有什么想法吗?!
更新: 所有代码都在头文件中。除了“*”运算符,我没问题。
关于“+”运算符,您能说些什么?我知道关于模板/运算符/转换的一切......但是这个问题就像我的 gcc 编译器的错误!?我写了一个转换运算符,这个运算符在“+”运算符之前调用,但我不知道为什么它不执行“*”运算符!
最佳答案
这个问题或多或少是经典的。重载决议开始于
建立一个可能的功能列表;在这种情况下,函数名为
operator*
.为此,它添加所有 operator*
其中的功能
列表的作用域,并尝试通过以下方式实例化所有函数模板
应用类型扣除;如果类型推导成功,它会添加
将模板实例化到列表中。 (函数模板是
不是函数。函数模板的实例化是
功能。)
模板类型推导的规则与使用的规则不同
过载决议。特别是,只有非常小的一组
转换被考虑。用户定义的转换运算符不是
经过考虑的。结果是在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* 内部进行转换。 (我没试过,
我不确定,但我认为你现有的 operator*
应该
被认为“更专业”,因此在类型时被选择
两者都推演成功。)
话虽如此,我认为您的做法是错误的。
你真的想要 m1 * m2
的返回类型吗?和 m2 * m1
成为
不同的。对于初学者,我需要客户端代码来制作
显式转换(您当前的代码就是这种情况);如果你这样做
想要支持隐式转换,我认为你需要做
operator*
一个全局的,使用某种简单的元编程来
确定正确的返回类型(即给定矩阵 long
和
unsigned
,您可能希望返回类型为 unsigned long
,
因为这是这些类型的混合类型算术给出的结果
否则),将两边都转换为目标类型,然后进行算术运算
在上面。很多工作可能不是很重要或
有用的功能。 (当然,只是我的意见。如果你的客户真的
想要混合类型算法,并愿意为此付出代价……)
关于c++ - Matrix 中没有 'operator *' 的匹配运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8587024/