【发布时间】:2017-12-05 18:46:21
【问题描述】:
我正在编写一个c++模板函数,旨在计算一个矩阵的函数,其中矩阵类型是一个模板参数。将它与犰狳库一起使用时,编译时出现意外失败。 我正在使用犰狳 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;
}
为了说明,我定义了两个函数sq 和sqgen,它们基本上做同样的工作。当模板参数MatrixClass 为arma::Mat<double> 时,sq 是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 应该在上面的代码中完全等于sq,我推测编译器没有正确推断出sqgen(id - m) 中的模板参数MatrixClass。
实际上,在替换时
arma::Mat<double> m_id2gen(sqgen(id - m));
与
arma::Mat<double> m_id2gen(sqgen(arma::Mat<double>(id - m)));
代码编译正确。
【问题讨论】: