매트릭스 형식이 템플릿 매개 변수 인 매트릭스 함수 계산을 목표로 C++ 템플릿 함수를 작성했습니다. armadillo 라이브러리와 함께 사용할 때 컴파일이 예기치 않게 실패합니다. 저는 armadillo 8.300과 gcc 7.2.0을 사용하고 있습니다. 다음은이 문제를 설명하는 테스트 프로그램입니다. armadillo 라이브러리를 사용하여 예기치 않은 (잘못된) 템플릿 공제
#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;
}
은 그림을 위해 나는 두 가지 기능
sq
와 본질적으로 같은 일을 할
sqgen
을 정의했다.
sq
은 템플릿 매개 변수
MatrixClass
이
arma::Mat<double>
일 때
sqgen
의 명시적인 인스턴스입니다.
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
의 마지막 호출에있다 :
g++ -std=c++14 -Wall -pedantic -O3 -o test test.cpp -lstdc++ -larmadillo
와 컴파일 오류를주고 실패. sqgen(m)
으로 전화해도 문제가되지 않지만 sqgen(id - m)
으로 전화하면 오류가 발생합니다. 대신 sq(id - m)
호출을 사용하는 것은 완전히 합법적입니다. 기능 sqgen
이어야하기 때문에, sq
정확하게 일치 위의 코드에서, 나는 컴파일러는 sqgen(id - m)
에 올바르게 템플릿 매개 변수 MatrixClass
추론하지 않는 가정.
arma::Mat<double> m_id2gen(sqgen(arma::Mat<double>(id - m)));
코드로
arma::Mat<double> m_id2gen(sqgen(id - m));
대체에 따라 사실 이 제대로 컴파일합니다.
을 시도합니다. – Yakk
@Yakk 좋아, 잘 잡는다. 귀하의 대답이 더 적절합니다. – bnaecker
제안 된 솔루션 중 어느 것도 작동하지 않습니다. 컴파일러는 eval()을 추가하더라도''error : 'operator ='와 일치하지 않습니다 (피연산자 유형은 'arma :: eGlue, arma :: Mat , arma :: eglue_minus>' 및 'arma :: Mat ')'''. Operator * = one은 유사한 오류를 obatins합니다.''error : 'operator * ='와 일치하지 않습니다 (피연산자 유형은 'arma :: eGlue , arma :: Mat , arma :: eglue_minus> '와'const arma :: eGlue , arma :: Mat , arma :: eglue_minus> ')''' –
francesco