I am using the armadillo library to perform calculations with matrices, vectors, and other herbs .
To speed up build times, I'm trying to compile the instantiations into a single file, and declare all the templates as extern
the files .cpp
they're used in:
// Un archivo.cpp
#include <armadillo>
extern template class arma::SpMat< arma::uword >;
extern template class arma::SpMat< arma::sword >;
...
Centralizing all used instances in a new file:
// armadillo.cpp
#include <armadillo>
template class arma::SpMat< arma::uword >;
template class arma::SpMat< arma::sword >;
...
But, when trying to compile the file armadillo.cpp
:
In instantiation of 'static void arma::arrayops::clean(eT*, arma::uword, eT, const typename arma::arma_not_cx::result*) [with eT = long long unsigned int; weapon::uword = long long unsigned int; typename weapon::arma_not_cx::result = long long unsigned int]':
required from 'const weapon::SpMat& weapon::SpMat::clean(typename weapon::get_pod_type::result) [with eT = long long unsigned int; typename weapon::get_pod_type::result = long long unsigned int]'
error: call of overloaded
abs(long long unsigned int&)
is ambiguous
val = (std::abs(val) <= abs_limit) ? eT(0) : val;
The protest refers to the first instance, arma::uword
. The piece of code responsible is:
template<typename eT>
arma_hot
inline
void
arrayops::clean(eT* mem, const uword n_elem, const eT abs_limit, const typename arma_not_cx<eT>::result* junk)
{
arma_ignore(junk);
for(uword i=0; i<n_elem; ++i)
{
eT& val = mem[i];
val = (std::abs(val) <= abs_limit) ? eT(0) : val;
}
}
Of course, before trying this centralization , everything compiled and worked fine.
I understand that the complaint refers to the fact that several possible instantiations of std::abs( )
are likely to compile properly for the type arma::uword
. What creeps me out is that it only complains when doing explicit instantiation .
Is there a difference between explicit instantiation and on-the-fly instantiation ?
What am I doing wrong ?
How do I solve it ?
Yes, in explicit instantiation absolutely the entire template is compiled, whereas in on-the-fly instantiation only those functions of the template that are actually used are compiled.
What is happening is that the function
arma::SpMat<arma::uword>::clean()
has no use in your code and that is why no error has been thrown, but by forcing an explicit implementation the function is compiled and that is where the problems begin to appear.What happens is that
std::abs
it does not have an implementation for unsigned types... something consistent since in unsigned types the absolute value always coincides with the original value.You can create an overload of
std::abs
for the type that is giving you trouble:Not the most elegant solution but it should work
Another solution would be to template the problematic calls.
Nothing prevents you from using a template that interfaces between your code and the call to
abs
, for example:In this way you avoid the error without many complications: