我有3x3 Matrix
和3x1 Vector
个类。我有两个乘法运算符;一个用于将矩阵与一个标量相乘,另一个用于将矩阵与矢量对象相乘。矩阵 - 标量乘法运算符是Matrix
类中的成员,矩阵向量乘法运算符是全局的。
#include <initializer_list>
#include <array>
template <class T>
class Matrix
{
public:
Matrix(std::initializer_list<T> List);
Matrix() : Matrix({0,0,0,0,0,0,0,0,0}) {}
template <class S> // THE COMPILER TRIES TO USE
Matrix<T> operator*(const S & Scalar); // THIS OPERATOR IN BOTH CASES.
const T & operator()(size_t i, size_t j) const;
private:
static constexpr size_t SIZE = 3;
static constexpr size_t AREA = SIZE * SIZE;
std::array<T, AREA> E;
};
template <class T>
Matrix<T>::Matrix(std::initializer_list<T> List)
{
if (List.size() != AREA) throw("Error!");
for (size_t i=0; i<AREA; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Matrix<T>::operator()(size_t i, size_t j) const
{
return E[SIZE * j + i];
}
template <class T>
template <class S>
Matrix<T> Matrix<T>::operator*(const S & Scalar)
{
const T ScalarT = static_cast<T>(Scalar);
Matrix<T> Result;
for (size_t i=0; i<AREA; i++)
{
Result.E[i] = E[i] * ScalarT;
}
return Result;
}
template <class T>
class Vector
{
public:
Vector(std::initializer_list<T> List);
Vector() : Vector({0,0,0}) {};
const T & operator()(size_t i) const;
T & operator()(size_t i);
private:
static constexpr size_t SIZE = 3;
std::array<T, SIZE> E;
};
template <class T>
Vector<T>::Vector(std::initializer_list<T> List)
{
if (List.size() != SIZE) throw("Error!");
for (size_t i=0; i<SIZE; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Vector<T>::operator()(size_t i) const
{
return E[i];
}
template <class T>
T & Vector<T>::operator()(size_t i)
{
return E[i];
}
template <class T> // THE COMPILER NEVER TRIES USING THIS GLOBAL OPERATOR.
Vector<T> operator*(const Matrix<T> & Mat, const Vector<T> & Vec)
{
Vector<T> Result;
Result(0) = Mat(0,0) * Vec(0) + Mat(0,1) * Vec(1) + Mat(0,2) * Vec(2);
Result(1) = Mat(1,0) * Vec(0) + Mat(1,1) * Vec(1) + Mat(1,2) * Vec(2);
Result(2) = Mat(2,0) * Vec(0) + Mat(2,1) * Vec(1) + Mat(2,2) * Vec(2);
return Result;
}
int wmain(int argc, wchar_t *argv[]/*, wchar_t *envp[]*/)
{
Matrix<float> Mat1({2, 0, 0,
0, 2, 0,
0, 0, 2});
Vector<float> Vec1({1,
2,
3});
Matrix<float> Mat2 = Mat1 * 2; // Matrix-Scalar Multiplication
Vector<float> Vec2 = Mat1 * Vec1; // Matrix-Vector Multiplication
return 0;
}
问题是,当我尝试进行矩阵向量乘法时,编译器选择并尝试使用矩阵 - 标量乘法运算符,并给出编译器错误。
如果删除矩阵标量乘法运算符和我使用它的行,程序将成功运行。相反,如果我删除矩阵向量乘法运算符,它再次成功运行。他们只是不相处。当它运行时(在任何一种情况下),它都能正确地进行所有计算。
这里出了什么问题?
编译器&amp; IDE:Microsoft Visual Studio 2015社区版
答案 0 :(得分:0)
在搜索重载以检查所有可能的范围时,语言未指定。一旦找到一个候选者,只有该范围内的重载用于选择最佳候选者。如果该候选人由于其他原因而未能编译,则仍不会检查其他范围。
因此,在您的情况下,因为标量是模板参数,它将匹配任何类型,因此只要运算符的左侧操作数是Matrix<T>
,标量乘法将匹配任何右侧操作数。
你可以:
operator*
放在相同的范围内,这样就可以考虑重载决策。operator
,例如Scalar<T>
,它是围绕标量类型而不是通用模板类型的瘦包装。