如何围绕表达式模板编写第三方库包装器类 [英] How to write a third-party library wrapper class around expression templates

查看:94
本文介绍了如何围绕表达式模板编写第三方库包装器类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在尝试在我的研究小组中实施新的C ++代码,以执行大型数值模拟(有限元,有限差分法,拓扑优化等).该软件将被学术界和行业人士使用.

We are trying to implement a 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 alike.

对于该软件的稠密线性代数,我们想使用Eigen或Armadillo.我们希望围绕这些软件包构建一个包装器,其原因有两个:1.向用户而不是第三方API公开我们自己的API; 2.如果将来需要切换库.我知道原因2是一种非常昂贵的保险形式,但是我们在以前的模拟软件中遇到过这种情况.

For the dense linear algebra piece of the software, we want to use either Eigen or Armadillo. We wish to build a wrapper around these packages for two reasons: 1. to expose our own API to the users rather than the third-party API; and 2. in case we need to switch libraries in the future. I understand reason 2 is a very expensive form of insurance, but we encountered this situation with our previous simulation software.

我遇到的有关包装第三方库的信息来自以下来源:

The information I have encountered regarding wrapping third-party libraries comes from these sources:

https://softwareengineering.stackexchange. com/questions/107338/using-third-party-libraries-always-use-a-wrapper

我的问题与构建此包装器类的最佳方法有关.理想情况下,最好使用薄层包装纸,例如:

My question relates as to the best way to build this wrapper class. Ideally, a thin layer wrapper would be the best, as:

template< typename T >
class my_vec {
private:
    arma::Col< T > _arma_vec;
};

或等价于特征向量的

然后,我的班级将第三方库类称为:

Then, my class would call the third-party library class as:

my_vec::foo() { return _arma_vec.foo(); }

我认为(我想对此进行确认),这个薄层的问题是我失去了从这些库在后台实现的表达式模板所获得的速度.例如,在犰狳中,以下操作:

I think (and I would like confirmation on this) that the issue with this thin layer is that I lose the speed gained from the expression templates these libraries have implemented under the hood. For example, in Armadillo, the following operation:

// Assuming these vectors were already populated.
a =  b + c + d;

变成这样的东西:

for ( std::size_t i = 0; i < a.size(); ++i ) {
    a[i] = b[i] + c[i] + d[i];
}

由于实现了表达式模板而没有创建任何临时对象.同样的情况也适用于本征.

without creating any temporaries due to their implementation of expression templates. The same situation applies to Eigen.

据我了解,之所以失去表达模板的功能,是因为Armadillo或Eigen不会创建自己的临时模板,而我的类my_vec却可以.避免这种情况的唯一方法是也围绕它们的表达模板构建一个薄层包装器.但是,在这一点上,这似乎违反了YAGNI原则.

As far as I undertand, the reason I lose the power of expression templates is that while Armadillo or Eigen do not create temporaries of their own, my class my_vec does. The only way to circumvent this would be to build a thin layer wrapper around their expression templates as well. However, at this point, this seems to be a violation of the YAGNI principle.

这里的相关问题:

建议使用类似的内容:

my_vec a, b, c;
// ... populate vectors
a._arma_vec = b._arma_vec + c._arma_vec;

是否可以改用这样的东西?

Is it possible to use something like this instead?

template< typename T >
arma::Col< T > &
my_vec< T >::data() { return _arma_vec; }

a.data() = b.data() + c.data();

还是使用一些运算符重载来向用户隐藏data()? 如果我们不希望直接使用这些库,还有哪些其他选择?使用宏?如果我们决定使用C ++ 11,会使用别名吗?

Or use some operator overloading to hide data() from the user? What other alternatives are there if we do not wish to use the libraries directly? Using macros? Using aliases if we decide to use C++11?

或者构建该包装器类的最便捷方法是什么?

Or what would be the most convenient way to build this wrapper class?

推荐答案

仅供以后参考,这就是我决定实现我的解决方案的方式:我通过以下方式重载了operator +:

Just for future reference, this is how I decided to implement my solution: I overloaded the operator+ in the following way:

template< typename T1, typename T2 >
auto
operator+(
        const my_vec< T1 > & X,
        const my_vec< T2 > & Y ) ->decltype( X.data() + Y.data() )
{
    return X.data() + Y.data();
}

template< typename T1, typename T2 >
auto
operator+(
        const my_vec< T1 > & X,
        const T2 &           Y ) ->decltype( X.data() + Y )
{
    return X.data() + Y;
}

template< typename T1, typename T2 >
auto
operator+(
        const T1 &           X,
        const my_vec< T2 > & Y ) ->decltype( X + Y.data() )
{
    return X + Y.data();
}

然后,我用以下代码重载了my_vec类中的operator =:

Then, I overloaded my operator= in my_vec class with the following:

template< typename T >
template< typename A >
const my_vec< T > &
my_vec< T >::operator=(
        const A & X )
{
    _arma_vec = X;

    return *this;
}

这篇关于如何围绕表达式模板编写第三方库包装器类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆