We are trying to introduce new C ++ code in my research group to perform large numerical simulations (finite elements, finite difference methods, topology optimization, etc.). The software will be used by people from academia and industry.
For the dense part of linear software algebra, we want to use either Eigen or Armadillo. We want to create a wrapper around these packages for two reasons: 1. expose our own API for users, not a third-party API; and 2. if necessary, switch libraries in the future. I understand that reason 2 is a very expensive form of insurance, but we are faced with this situation with our previous simulation software.
Information related to the wrapping of third-party libraries was obtained from the following sources:
My question is about the best way to create this wrapper class. Ideally, a thin layer shell would be better because:
template< typename T > class my_vec { private: arma::Col< T > _arma_vec; };
or its equivalent with an eigenvector.
Then my class will call a third-party library class as follows:
my_vec::foo() { return _arma_vec.foo(); }
I think (and I would like to confirm this) that the problem with this thin layer is that I am losing the speed obtained from the expression templates that these libraries implemented under the hood. For example, in Armadillo, the following operation:
becomes something like this:
for ( std::size_t i = 0; i < a.size(); ++i ) { a[i] = b[i] + c[i] + d[i]; }
without creating temporary times due to their implementation of expression patterns . The same situation applies to Eigen.
As far as I understand, the reason I lose the power of expression patterns is that although Armadillo or Eigen do not create time series, my class my_vec does. The only way around this would be to create a thin layer wrapper around their expression patterns. However, at the moment this, apparently, is a violation of the YAGNI principle.
This related question is here:
suggests using something like:
my_vec a, b, c;
Is it possible to use something like this?
template< typename T > arma::Col< T > & my_vec< T >::data() { return _arma_vec; } a.data() = b.data() + c.data();
Or use some operator overloading to hide data () from the user? What other alternatives exist if we do not want to use libraries directly? Using macros? Using aliases if we decide to use C ++ 11?
Or what would be the most convenient way to create this wrapper class?