私は行列の関数を計算するためのC++テンプレート関数を書いています。行列の型はテンプレートパラメータです。 armadilloライブラリで使用すると、予期せぬコンパイルエラーが発生します。 私はarmadillo 8.300とgcc 7.2.0を使用しています。 以下では、問題を説明するテストプログラムです。 アルマジロライブラリを使用した、予期しない(間違った)テンプレートの控除
#include <armadillo>
arma::Mat<double> sq(const arma::Mat<double>& M)
{
arma::Mat<double> res(M);
res = res * M;
return res;
}
template <class MatrixClass>
MatrixClass sqgen(const MatrixClass& M)
{
MatrixClass res(M);
res = res * M;
return res;
}
int main()
{
arma::Mat<double> id(3, 3, arma::fill::eye);
arma::Mat<double> m(3, 3, arma::fill::ones);
arma::Mat<double> m2(sq(m));
arma::Mat<double> m_id2(sq(id - m));
arma::Mat<double> m2gen(sqgen(m));
arma::Mat<double> m_id2gen(sqgen(id - m)); // Error here
return 0;
}
は、例示のために私は2つの機能sq
と本質的に同じ仕事をsqgen
を定義しました。 sq
は、テンプレートパラメータMatrixClass
がarma::Mat<double>
の場合の明示的なインスタンス化sqgen
です。
g++ -std=c++14 -Wall -pedantic -O3 -o test test.cpp -lstdc++ -larmadillo
と、コンパイルエラーを与える失敗:
test.cpp: In instantiation of ‘MatrixClass sq(const MatrixClass&) [with MatrixClass = arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>]’:
test.cpp:24:36: required from here
test.cpp:14:7: error: no match for ‘operator=’ (operand types are ‘arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>’ and ‘arma::enable_if2<true, const arma::Glue<arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::glue_times> >::result {aka const arma::Glue<arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::glue_times>}’)
res = res * M;
~~~~^~~~~~~~~
In file included from /usr/include/armadillo:204:0,
from test.cpp:1:
/usr/include/armadillo_bits/eGlue_bones.hpp:22:7: note: candidate: arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>& arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>::operator=(const arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>&) <deleted>
class eGlue : public Base<typename T1::elem_type, eGlue<T1, T2, eglue_type> >
^~~~~
/usr/include/armadillo_bits/eGlue_bones.hpp:22:7: note: no known conversion for argument 1 from ‘arma::enable_if2<true, const arma::Glue<arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::glue_times> >::result {aka const arma::Glue<arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>, arma::glue_times>}’ to ‘const arma::eGlue<arma::Mat<double>, arma::Mat<double>, arma::eglue_minus>&’
問題はsqgen
の最後の呼び出しです。 sqgen(m)
を呼び出す際に問題はありませんが、sqgen(id - m)
という呼び出しでエラーが発生します。代わりに、sq(id - m)
というコールを使用することは完全に合法であることに注意してください。上記のコードでは、関数sqgen
は正確にに等しいはずなので、私は、コンパイラがテンプレートのパラメータMatrixClass
をsqgen(id - m)
に正しく推定しないと推測します。
arma::Mat<double> m_id2gen(sqgen(arma::Mat<double>(id - m)));
コードで
arma::Mat<double> m_id2gen(sqgen(id - m));
を代入する際に実際に は、正しくコンパイル。
を試してみてください。 – Yakk
@ヤク右、いいキャッチ。あなたの答えはより適切です。 – bnaecker
提案するソリューションはどれも動作しません。 eval()を追加しても、コンパイラは '' 'error: 'operator ='と一致しません(オペランドの型は 'arma :: eGlue、arma :: Mat 、arma :: eglue_minus>' and 'arma :: Mat ') '' '。オペレータ* = 1を使用すると、同様のエラーが発生します。エラー: 'operator * ='に一致しません(オペランドタイプは 'arma :: eGlue 、arma :: Mat 、arma :: eglue_minus> 'と' const arma :: eGlue 、arma :: Mat 、arma :: eglue_minus> ') '' ' –
francesco