I don't use templates often, but I started working with Armadillo's library which has several different array and matrix types, and I wanted to write templates to cover versatile inputs instead of several functions with the same name.
I found this post that outlines a "trick" how to convert Armadillo's reference to arma::Mat object, and figured, for arrays it should be:
template <typename T>
const arma::Col<T>& as_Col(const arma::Col<T>& m) {return m;};
template<typename T1, typename eop_type>
arma::Col<typename T1::elem_type> as_Col(const arma::eOp<T1, eop_type>& X) {return {X};};
So I made simple check_array_size and save_data functions:
template <typename VectorA, typename VectorB>
void check_array_size(const VectorA &A, const VectorB &B, const std::string &errorDescription)
{
const auto& AA = as_Col(A);
const auto& BB = as_Col(B);
if (AA.n_elem != BB.n_elem)
throw std::length_error(errorDescription);
}
and
template <typename VectorA, typename VectorB>
void save_data(const VectorA &x, const VectorB &y, const std::string &fileName, const bool append)
{
check_array_size(x,y,fileName);
const auto& xx = as_Col(x);
const auto& yy = as_Col(y);
std::ofstream out_stream;
if (append)
{
out_stream.open(fileName+".dat", std::ios_base::app);
out_stream << "" << std::endl;
}
else
out_stream.open(fileName+".dat");
const uword N = yy.n_elem;
for (uword i = 0; i < N; i++)
out_stream << xx.at(i) << " " << yy.at(i) << std::endl;
out_stream.close();
}
The compiler did not want to finish installing this, it failed on a code line that was trying to use save_data with arguments arma::vec and arma::uvec:
undefined reference to `void Nanosim::save_data<arma::Col<double>, arma::Col<unsigned long long> >(arma::Col<double> const&, arma::Col<unsigned long long> const&, std::string const&, bool)'
Now, I think I can solve this simply by removing calls to as_Col function and instantiating the template for save_data and check_array_size functions manually, for example:
template void save_data<arma::vec,arma::uvec>(const arma::vec&, const arma::uvec&, const std::string &, const bool);
but can someone please tell me what is going wrong, I have a hunch it's something simple, ie, wrong compiler, I am using C++17. I don't fully understand what as_Col function does, I simply want a neat way to write templates using Armadillo's matrix and array objects.