私はマトリックス基本クラスを書いており、タイトルとして問題に遭遇しました。
私の申告書です。
template <typename T, size_t m, size_t n, typename _Prd>
template <size_t _m, size_t _n>
const Matrix<T,m,_n,_Prd> operator* (const Matrix<T,m,n,_Prd>& lhs, const Matrix<T,_m,_n,_Prd>& rhs) ; // matrix mult
そしてクラス内でフレンド宣言。
template <size_t _m, size_t _n>
friend const Matrix<T,m,_n,_Prd> operator* <>(const Matrix<T,m,n,_Prd>& lhs, const Matrix<T,_m,_n,_Prd>& rhs) ;
そして実装:
template <typename T, size_t m, size_t n, typename _Prd>
template <size_t _m, size_t _n>
const Matrix<T,m,_n,_Prd> operator* (const Matrix<T,m,n,_Prd>& lhs, const Matrix<T,_m,_n,_Prd>& rhs)
{
assert (n == _m) ;
Matrix<T,m,_n,_Prd> result ;
for (size_t j = 0 ; j < m ; ++j)
for (size_t i = 0 ; i < _n ; ++ i)
for (size_t k = 0 ; k < n ; ++ k)
result.at(j,i) += lhs.at(j,k) * rhs.at(k,i) ;
return result ;
}
ただし、これらはコンパイルされません。エラーは次のとおりです。
In file included from main.cpp:13:
Matrix.hpp:43: error: too many template-parameter-lists
Matrix.hpp:66: error: invalid use of template-id ‘operator*<>’ in declaration of primary template
In file included from main.cpp:13:
Matrix.hpp:364: error: too many template-parameter-lists
ここで同じクラスで別の問題に遭遇しました 元のテンプレートタイプとは異なるテンプレートタイプを返すときに一致する関数はありません
更新:
以下の提案に従って修正しましたが、それでも機能しません。
前方宣言:
template <typename T, size_t m, size_t n, typename _Prd,size_t _m, size_t _n>
const Matrix<T,m,_n,_Prd> operator* (const Matrix<T,m,n,_Prd>& lhs, const Matrix<T,_m,_n,_Prd>& rhs) ; // matrix mult
クラス内のフレンド宣言:
template <size_t _m, size_t _n>
friend const Matrix<T,m,_n,_Prd> operator* (const Matrix<T,m,n,_Prd>& lhs, const Matrix<T,_m,_n,_Prd>& rhs) ;
実装 :
template <typename T, size_t m, size_t n, typename _Prd,size_t _m, size_t _n>
const Matrix<T,m,_n,_Prd> operator* (const Matrix<T,m,n,_Prd>& lhs, const Matrix<T,_m,_n,_Prd>& rhs)
{
assert (n == _m) ;
Matrix<T,m,_n,_Prd> result ;
for (size_t j = 0 ; j < m ; ++j)
for (size_t i = 0 ; i < _n ; ++ i)
for (size_t k = 0 ; k < n ; ++ k)
result.at(j,i) += lhs.at(j,k) * rhs.at(k,i) ;
return result ;
}
しかし、次のように使用したい場合:
Matrix<double,2,3> testmat8(10.0) ;
Matrix<double,3,4> testmat9(2.0) ;
Matrix<double,2,4> testmat10 ;
testmat10 = testmat8 * testmat9 ;
エラーは次のとおりです。
main.cpp:143: undefined reference to `Matrix<double, 2ul, 4ul, std::equal_to<double> > const operator*<3ul, 4ul>(Matrix<double, 2ul, 3ul, std::equal_to<double> > const&, Matrix<double, 3ul, 4ul, std::equal_to<double> > const&)'
まだ未解決…
アップデート2:
目的を明確にするために、3 つの回避策をコーディングしました。ただし、すべてが期待どおりに機能するわけではありません。
//member operator * rather than friend function
template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n>
Matrix<T,m,_n,_Prd> Matrix<T,m,n,_Prd>::operator *(const Matrix<T,_m,_n,_Prd> & rhs) const
{
assert (n == _m) ;
Matrix<T,m,_n,_Prd> result ;
for (size_t j = 0 ; j < m ; ++j)
for (size_t i = 0 ; i < _n ; ++ i)
for (size_t k = 0 ; k < n ; ++ k)
result.at(j,i) += this->at(j,k) * rhs.at(k,i) ;
return result ;
}
//work around for *
template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n>
void Matrix<T,m,n,_Prd>::mul (Matrix<T,m,_n,_Prd> & result, const Matrix<T,m,n,_Prd> & A, const Matrix<T,_m,_n,_Prd> & B)
{
assert (n == _m) ;
for (size_t j = 0 ; j < m ; ++j)
for (size_t i = 0 ; i < _n ; ++ i)
for (size_t k = 0 ; k < n ; ++ k)
result.at(j,i) += A.at(j,k) * B.at(k,i) ;
}
template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n>
Matrix<T,m,_n,_Prd> Matrix<T,m,n,_Prd>::mul(const Matrix<T,_m,_n,_Prd> & B) const
{
assert (n == _m) ;
Matrix<T,m,_n,_Prd> result ;
for (size_t j = 0 ; j < m ; ++j)
for (size_t i = 0 ; i < _n ; ++ i)
for (size_t k = 0 ; k < n ; ++ k)
result.at(j,i) += this->at(j,k) * B.at(k,i) ;
return result ;
}
そして、私はそれらを次のように呼びます。
testmat10 = testmat8 * testmat9 ; //works, but I have to comment out the friend operator * overload outside of the class.
testmat10 = testmat8.mul(testmat9) ; //works, but mul() has to be a member, not as expected as a friend .
Matrix<double,2,3>::mul(testmat10, testmat8, testmat9) ;
//works, but this is ridiculous, for a static function, how would I avoid use <double,2,3> as the testmat8's template before using mul? I shouldn't have used template when I use mul in this way.
しかし、私が望む答えは、非メンバー演算子 * が最初の mul() と同じことができない理由を誰かが明らかにできるということですか? そして、私の行列乗算関数をコーディングする適切な方法は何ですか?
Update3: (解決済み) jpalecek のおかげで、彼の回答に従ってコードを修正しました。
前方宣言:
template < typename T, size_t m, size_t n, typename _Prd, size_t _m, size_t _n>
const Matrix<T,m,_n,_Prd> operator * (const Matrix<T,m,n,_Prd>& lhs, const Matrix<T,_m,_n,_Prd> & rhs) ;
友達宣言:
// here is tricky
template <typename U, size_t mm, size_t nn, typename _Prd2, size_t _m, size_t _n>
friend const Matrix<U,mm,_n,_Prd2> operator* (const Matrix<U,mm,nn,_Prd2>& lhs, const Matrix<U,_m,_n,_Prd2>& rhs) ;
実装:
template <typename U, size_t mm, size_t nn, typename _Prd2, size_t _m, size_t _n>
const Matrix<U,mm,_n,_Prd2> operator* (const Matrix<U,mm,nn,_Prd2>& lhs, const Matrix<U,_m,_n,_Prd2>& rhs)
{
return lhs.mul(rhs) ;
}
メンバー関数としての mul():
template <typename T, size_t m, size_t n, typename _Prd>
template<size_t _m, size_t _n>
Matrix<T,m,_n,_Prd> Matrix<T,m,n,_Prd>::mul(const Matrix<T,_m,_n,_Prd> & B) const
{
assert (n == _m) ;
Matrix<T,m,_n,_Prd> result ;
for (size_t j = 0 ; j < m ; ++j)
for (size_t i = 0 ; i < _n ; ++ i)
for (size_t k = 0 ; k < n ; ++ k)
result.at(j,i) += this->at(j,k) * B.at(k,i) ;
return result ;
}
使用法:
//test * operator, all work
Matrix<double,2,3> testmat8(10.0) ;
Matrix<double,3,4> testmat9(2.0) ;
Matrix<double,4,4> testmat11(3.0) ;
Matrix<double,2,4> testmat10 ;
testmat10 = testmat8 * testmat9 * testmat11;
cout <<testmat10<<endl ;
testmat10 = testmat8.mul(testmat9) ;
cout << testmat10 << endl ;