Saya memiliki kelas 3x3 Matrix
dan 3x1 Vector
. Saya memiliki dua operator perkalian; satu untuk mengalikan matriks dengan skalar, satu lagi untuk mengalikan matriks dengan objek vektor. Operator perkalian matriks-skalar adalah anggota dalam kelas Matrix
dan operator perkalian matriks-vektor bersifat global.
#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;
}
Masalahnya, ketika saya mencoba melakukan perkalian matriks-vektor, compiler memilih dan mencoba menggunakan operator perkalian matriks-skalar, dan memberikan error compiler.
Jika saya menghapus operator perkalian matriks-skalar dan baris tempat saya menggunakannya, maka program berhasil berjalan. Sebaliknya, jika saya menghapus operator perkalian matriks-vektor, operator tersebut berhasil dijalankan kembali. Mereka hanya tidak akur. Dan ketika dijalankan (dalam kedua kasus), ia membuat semua perhitungan dengan benar.
Apa yang salah di sini?
Kompiler & IDE: Edisi Komunitas Microsoft Visual Studio 2015
template<class S>
...(const S&)
cocok dengan semua objek. Itu tidak berarti hanya tipe skalar atau semacamnya - person M.M   schedule 08.03.2016operator*
non-anggota. (Ini mungkin tidak akan menyelesaikan masalah Anda tetapi mungkin menghilangkan beberapa faktor yang mengganggu atau perancu) - 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
sebagai ganti parameter templat yang berbeda. - person Simon Kraemer   schedule 08.03.2016T
untuk operator anggota Anda? - person Simon Kraemer   schedule 08.03.2016const Vector<T>&
lebih disukai daripadaconst S&
, tidak ada yang menjadi rumit dalam operator anggota vs. nonanggota, setidaknya di sini anggotaoperator*
mungkin harus memenuhi syarat const, meskipun dentang masih menganggapnya ambigu - person Piotr Skotnicki   schedule 08.03.2016T
yang akan menyelesaikan masalah Anda. Hal ini juga harus mengurangi rawan kesalahan. Melewati mis. sebuah pointer tidak masuk akal tetapi berfungsi dengan pendekatan Anda saat ini. Tetapi perhatikan juga hal-hal seperti kebenaran const dan hal-hal lain yang disebutkan dalam komentar di atas. - person Simon Kraemer   schedule 08.03.2016return *this;
di operator anggota ;-) - person Simon Kraemer   schedule 08.03.2016T
digunakan dua kali, untukMatrix
danVector
, jadi dentang mungkin berpikir bahwa tidak ada yang lebih terspesialisasi daripada yang lain, sehingga menimbulkan ambiguitas.Matrix<float>
lebih terspesialisasi dariMatrix<T>
, sama seperticonst Vector<T>&
lebih terspesialisasi dariconst S&
- person Piotr Skotnicki   schedule 08.03.2016operator*
menjadi anggota global, dan membiarkanT
dariMatrix<T>
disimpulkan (seperti pada versiVector<T>
) - person Piotr Skotnicki   schedule 08.03.2016Matrix<float>::operator*
atauMatrix<T>::operator*
? - person n. 1.8e9-where's-my-share m.   schedule 08.03.2016Matrix<float>
, maka kompiler berakhir dengan dua kelebihan:template<class S> operator*(const Matrix<float>&, const S&)
dantemplate<class T> operator*(const Matrix<T>&, const Vector<T>&)
, yaitu kompiler melihatfloat
, karenaMatrix<float>
adalah parameter objek implisit - person Piotr Skotnicki   schedule 08.03.2016