https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62255
Bug ID: 62255 Summary: Introducing an unrelated template parameter causes failed compilation Product: gcc Version: 4.8.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: m at maxgerlach dot de Created attachment 33393 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33393&action=edit Archive containing output.txt, arma_template_test.ii and arma_no_template_test.ii Adding a template parameter to a class causes compilation to fail, even though no further use of this parameter is made. This problem shows up by using any recent release of the Armadillo C++ library (header only, http://arma.sourceforge.net/) with gcc 4.8.2 (my system) and 4.8.3 (another system). On g++ 4.6.3, the Intel compiler 13.1 or clang 3.4 the problem does not appear. This is the version information from my system: $ g++ --version g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 1) Failing compilation command line: g++ -c arma_template_test.cpp -Wall -Wextra -std=c++11 -save-temps &> output.txt Please see attached error messages in output.txt and attached prepocessed file arma_template_test.ii. The error messages in output.txt are also repeated directly in this bug report below. Code arma_template_test.cpp: #include <armadillo> #include <iostream> template<int param> class Test { public: void compute() { arma::mat matrix = arma::randu(10,10); matrix = matrix + matrix.t(); arma::vec eigval; arma::mat eigvec; arma::eig_sym(eigval, eigvec, matrix); arma::mat exp_matrix = eigvec * arma::diagmat(arma::exp(eigval)) * arma::trans(eigvec); exp_matrix.print(std::cout); } }; int main() { Test<1> test; test.compute(); return 0; } 2) Successful compilation without warnings command line: g++ -c arma_no_template_test.cpp -Wall -Wextra -std=c++11 -save-temps Please see attached prepocessed file arma_no_template_test.ii Code arma_no_template_test.cpp: #include <armadillo> #include <iostream> class Test { public: void compute() { arma::mat matrix = arma::randu(10,10); matrix = matrix + matrix.t(); arma::vec eigval; arma::mat eigvec; arma::eig_sym(eigval, eigvec, matrix); arma::mat exp_matrix = eigvec * arma::diagmat(arma::exp(eigval)) * arma::trans(eigvec); exp_matrix.print(std::cout); } }; int main() { Test test; test.compute(); return 0; } 3) Error messages for failing compilation (output.txt): In file included from /usr/include/armadillo:105:0, from arma_template_test.cpp:1: /usr/include/armadillo_bits/traits.hpp: In instantiation of ‘const bool arma::is_Mat_fixed<arma::eOp<arma::Col<double>, arma::eop_exp> >::value’: /usr/include/armadillo_bits/diagmat_proxy.hpp:415:7: required from ‘class arma::diagmat_proxy_check<arma::eOp<arma::Col<double>, arma::eop_exp> >’ /usr/include/armadillo_bits/glue_times_meat.hpp:851:44: required from ‘static void arma::glue_times_diag::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times_diag>&) [with T1 = arma::Mat<double>; T2 = arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/Mat_meat.hpp:4377:28: required from ‘arma::Mat<eT>::Mat(const arma::Glue<T1, T2, glue_type>&) [with T1 = arma::Mat<double>; T2 = arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>; glue_type = arma::glue_times_diag; eT = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:82:25: required from ‘static void arma::glue_times_redirect2_helper<true>::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:318:81: required from ‘static void arma::glue_times_redirect<2u>::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:412:43: required from ‘static void arma::glue_times::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/Mat_meat.hpp:4377:28: required from ‘arma::Mat<eT>::Mat(const arma::Glue<T1, T2, glue_type>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; glue_type = arma::glue_times; eT = double]’ arma_template_test.cpp:14:94: required from ‘void Test<param>::compute() [with int param = 1]’ arma_template_test.cpp:22:18: required from here /usr/include/armadillo_bits/traits.hpp:67:23: error: non-constant in-class initialization invalid for static member ‘arma::is_Mat_fixed<arma::eOp<arma::Col<double>, arma::eop_exp> >::value’ { static const bool value = ( is_Mat_fixed_only<T>::value || is_Row_fixed_only<T>::value || is_Col_fixed_only<T>::value ); }; ^ /usr/include/armadillo_bits/traits.hpp:67:23: error: (an out of class initialization is required) /usr/include/armadillo_bits/traits.hpp:67:23: error: ‘arma::is_Mat_fixed<arma::eOp<arma::Col<double>, arma::eop_exp> >::value’ cannot be initialized by a non-constant expression when being declared In file included from /usr/include/armadillo:301:0, from arma_template_test.cpp:1: /usr/include/armadillo_bits/diagmat_proxy.hpp: In instantiation of ‘class arma::diagmat_proxy_check<arma::eOp<arma::Col<double>, arma::eop_exp> >’: /usr/include/armadillo_bits/glue_times_meat.hpp:851:44: required from ‘static void arma::glue_times_diag::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times_diag>&) [with T1 = arma::Mat<double>; T2 = arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/Mat_meat.hpp:4377:28: required from ‘arma::Mat<eT>::Mat(const arma::Glue<T1, T2, glue_type>&) [with T1 = arma::Mat<double>; T2 = arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>; glue_type = arma::glue_times_diag; eT = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:82:25: required from ‘static void arma::glue_times_redirect2_helper<true>::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:318:81: required from ‘static void arma::glue_times_redirect<2u>::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:412:43: required from ‘static void arma::glue_times::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/Mat_meat.hpp:4377:28: required from ‘arma::Mat<eT>::Mat(const arma::Glue<T1, T2, glue_type>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; glue_type = arma::glue_times; eT = double]’ arma_template_test.cpp:14:94: required from ‘void Test<param>::compute() [with int param = 1]’ arma_template_test.cpp:22:18: required from here /usr/include/armadillo_bits/diagmat_proxy.hpp:415:7: error: the value of ‘arma::is_Col_fixed_only<arma::eOp<arma::Col<double>, arma::eop_exp> >::value’ is not usable in a constant expression class diagmat_proxy_check : public diagmat_proxy_check_redirect<T1, is_Mat_fixed<T1>::value >::result ^ In file included from /usr/include/armadillo:105:0, from arma_template_test.cpp:1: /usr/include/armadillo_bits/traits.hpp:60:21: note: ‘arma::is_Col_fixed_only<arma::eOp<arma::Col<double>, arma::eop_exp> >::value’ was not initialized with a constant expression static const bool value = ( sizeof(check<T>(0)) == sizeof(yes) ); ^ In file included from /usr/include/armadillo:301:0, from arma_template_test.cpp:1: /usr/include/armadillo_bits/diagmat_proxy.hpp:415:7: note: in template argument for type ‘bool’ class diagmat_proxy_check : public diagmat_proxy_check_redirect<T1, is_Mat_fixed<T1>::value >::result ^ In file included from /usr/include/armadillo:564:0, from arma_template_test.cpp:1: /usr/include/armadillo_bits/glue_times_meat.hpp: In instantiation of ‘static void arma::glue_times_diag::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times_diag>&) [with T1 = arma::Mat<double>; T2 = arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>; typename T1::elem_type = double]’: /usr/include/armadillo_bits/Mat_meat.hpp:4377:28: required from ‘arma::Mat<eT>::Mat(const arma::Glue<T1, T2, glue_type>&) [with T1 = arma::Mat<double>; T2 = arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>; glue_type = arma::glue_times_diag; eT = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:82:25: required from ‘static void arma::glue_times_redirect2_helper<true>::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:318:81: required from ‘static void arma::glue_times_redirect<2u>::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/glue_times_meat.hpp:412:43: required from ‘static void arma::glue_times::apply(arma::Mat<typename T1::elem_type>&, const arma::Glue<T1, T2, arma::glue_times>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; typename T1::elem_type = double]’ /usr/include/armadillo_bits/Mat_meat.hpp:4377:28: required from ‘arma::Mat<eT>::Mat(const arma::Glue<T1, T2, glue_type>&) [with T1 = arma::Glue<arma::Mat<double>, arma::Op<arma::eOp<arma::Col<double>, arma::eop_exp>, arma::op_diagmat>, arma::glue_times_diag>; T2 = arma::Op<arma::Mat<double>, arma::op_htrans>; glue_type = arma::glue_times; eT = double]’ arma_template_test.cpp:14:94: required from ‘void Test<param>::compute() [with int param = 1]’ arma_template_test.cpp:22:18: required from here /usr/include/armadillo_bits/glue_times_meat.hpp:855:30: error: ‘const class arma::diagmat_proxy_check<arma::eOp<arma::Col<double>, arma::eop_exp> >’ has no member named ‘n_elem’ const uword B_n_elem = B.n_elem; ^ /usr/include/armadillo_bits/glue_times_meat.hpp:863:23: error: no match for ‘operator[]’ (operand types are ‘const arma::diagmat_proxy_check<arma::eOp<arma::Col<double>, arma::eop_exp> >’ and ‘arma::uword {aka unsigned int}’) const eT val = B[col]; ^ /usr/include/armadillo_bits/glue_times_meat.hpp:891:30: error: ‘const class arma::diagmat_proxy_check<arma::eOp<arma::Col<double>, arma::eop_exp> >’ has no member named ‘n_elem’ const uword B_n_elem = B.n_elem; ^ /usr/include/armadillo_bits/glue_times_meat.hpp:899:29: error: no match for ‘operator[]’ (operand types are ‘const arma::diagmat_proxy_check<arma::eOp<arma::Col<double>, arma::eop_exp> >’ and ‘arma::uword {aka unsigned int}’) out.at(i,i) = A[i] * B[i]; ^