ฉันมีคลาส 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;
}
ปัญหาคือ เมื่อฉันพยายามคูณเมทริกซ์-เวกเตอร์ คอมไพลเลอร์จะเลือกและพยายามใช้ตัวดำเนินการคูณเมทริกซ์-สเกลาร์ และทำให้คอมไพเลอร์เกิดข้อผิดพลาด
ถ้าฉันลบตัวดำเนินการคูณเมทริกซ์-สเกลาร์และบรรทัดที่ฉันใช้ โปรแกรมจะทำงานได้สำเร็จ ในทางกลับกัน ถ้าฉันลบตัวดำเนินการคูณเมทริกซ์-เวกเตอร์ มันจะรันได้สำเร็จอีกครั้ง พวกเขาแค่ไม่เข้ากัน และเมื่อมันทำงาน (ไม่ว่าในกรณีใด) การคำนวณทั้งหมดก็จะถูกต้อง
เกิดอะไรขึ้นที่นี่?
คอมไพเลอร์และ IDE: Microsoft Visual Studio 2015 Community Edition
template<class S>
...(const S&)
ตรงกับวัตถุทั้งหมด มันไม่ได้หมายถึงเฉพาะประเภทสเกลาร์หรืออะไรสักอย่าง - person M.M   schedule 08.03.2016operator*
(วิธีนี้อาจจะไม่ช่วยแก้ปัญหาของคุณได้ แต่อาจกำจัดปลาเฮอริ่งแดงหรือปัจจัยที่สับสนออกไปได้) - person M.M   schedule 08.03.2016Matrix<T> operator*(const S & Scalar) const
. - person n. 1.8e9-where's-my-share m.   schedule 08.03.2016T
แทนพารามิเตอร์เทมเพลตอื่น - person Simon Kraemer   schedule 08.03.2016T
สำหรับผู้ดำเนินการสมาชิกของคุณ? - person Simon Kraemer   schedule 08.03.2016const Vector<T>&
เป็นสิ่งที่ต้องการมากกว่าconst S&
ไม่มีอะไร ซับซ้อน ในตัวดำเนินการที่เป็นสมาชิกเทียบกับตัวดำเนินการที่ไม่เป็นสมาชิก อย่างน้อยที่นี่สมาชิกoperator*
ควรจะมีคุณสมบัติ const แม้ว่าเสียงดังกราวจะยังคงพบว่าคลุมเครือ - person Piotr Skotnicki   schedule 08.03.2016T
จะช่วยแก้ปัญหาของคุณได้ ควรมีข้อผิดพลาดน้อยลงด้วย ผ่าน เช่น ตัวชี้ไม่สมเหตุสมผล แต่ใช้ได้กับแนวทางปัจจุบันของคุณ แต่ยังดูแลสิ่งต่าง ๆ เช่น const-correctness และสิ่งอื่น ๆ ที่กล่าวถึงในความคิดเห็นด้านบน - person Simon Kraemer   schedule 08.03.2016return *this;
ในตัวดำเนินการสมาชิก ;-) - person Simon Kraemer   schedule 08.03.2016T
ถูกใช้สองครั้งสำหรับMatrix
และVector
ดังนั้นเสียงดังกราวอาจคิดว่าไม่มีใครมีความเชี่ยวชาญมากกว่าอีกอันหนึ่ง ดังนั้นจึงมีความคลุมเครือMatrix<float>
มีความเชี่ยวชาญมากกว่าMatrix<T>
เช่นเดียวกับที่const Vector<T>&
มีความเชี่ยวชาญมากกว่าconst S&
- person Piotr Skotnicki   schedule 08.03.2016operator*
เป็นสมาชิกระดับโลก และให้อนุมานT
จากMatrix<T>
ได้ (เช่นเดียวกับในVector<T>
-version) - person Piotr Skotnicki   schedule 08.03.2016Matrix<float>::operator*
หรือMatrix<T>::operator*
- person n. 1.8e9-where's-my-share m.   schedule 08.03.2016Matrix<float>
คอมไพเลอร์จะจบลงด้วยการโอเวอร์โหลดสองครั้ง:template<class S> operator*(const Matrix<float>&, const S&)
และtemplate<class T> operator*(const Matrix<T>&, const Vector<T>&)
นั่นคือคอมไพเลอร์เห็นfloat
เนื่องจากMatrix<float>
เป็นพารามิเตอร์วัตถุโดยนัย - person Piotr Skotnicki   schedule 08.03.2016