繁体   English   中英

切片的 C++ 表达式模板

[英]C++ expression templates for slices

我正在重写一个 c++ FEM 库,其中我使用了表达式模板。 例如,在以前的版本中,我能够做到

BilinearForm s(mesh, Vh, Vh, [&gp, &mesh](const TrialFunction& u, const TestFunction& v) -> double
{
    return mesh.integrate(gp*dot(grad(u), grad(v)) );
});

这将自动评估 Vh 中每个试验和测试函数的表达式并返回一个稀疏矩阵。

代码相当繁琐,所以我想从这篇文章中获得一些灵感来重新编写它。 对于在单个元素上定义的函数来说,这相当简单。

template<typename E1, typename E2>
class ElementWiseScalarProd : public ElementWiseScalarExpression< ElementWiseScalarProd<E1, E2> >
{
public:
    ElementWiseScalarProd(const E1& lhs, const E2& rhs) : m_lhs(lhs), m_rhs(rhs) {}
public:
    inline double operator[] (const size_t k) const { return m_lhs[k] * m_rhs[k]; }
public:
    inline bool containsTrial() const { return m_lhs.containsTrial() or m_rhs.containsTrial(); }
    inline bool containsTest()  const { return m_lhs.containsTest() or m_rhs.containsTest(); }
public:
    inline const Element* getElement() const { assert(m_lhs.getElement() == m_rhs.getElement()); return m_lhs.getElement(); }
private:
    const E1& m_lhs;
    const E2& m_rhs;
};

但是,当我想乘以在整个网格上定义的 function 时,事情变得有点棘手。 my 运算符的返回类型变为数组或数组的切片。

template<typename E1, typename E2>
class FunctionProd : public FunctionExpression< FunctionProd<E1, E2> >
{
public:
    typedef ElementWiseScalarProd<E1::ElementWiseType, E2::ElementWiseType> ElementWiseType;
public:
    inline const ElementWiseType operator[] (const size_t e) const { return ElementWiseType(m_lhs[e], m_rhs[e]); }
public:
    inline const Mesh* getMesh() const { assert(m_lhs.getMesh() == m_rhs.getMesh()); return m_lhs.getMesh(); }
private:
    const E1& m_lhs;
    const E2& m_rhs;
};

看来,如果我将在元素上定义的 function 和在整个网格上定义的 function 相乘,我的 FunctionProd::operator[] 应该返回一个引用,但这意味着我需要存储它创建的 ZA8CFDE69't89't11它? 有没有办法绕过它?

提前致谢

你需要考虑你内心表达的价值类别。

您可以使用区分左值和右值的特征以及一堆完美转发来做到这一点。

template <typename T>
struct expression_holder {
    using type = T;
};

template <typename T>
struct expression_holder<const T> : expression_holder<T> {
};

template <typename T>
struct expression_holder<T &> {
    using type = const T &;
};

template <typename T>
struct expression_holder<T &&> {
    using type = T;
};

template <typename T>
using expression_holder_t = typename expression_holder<T>::type;

template<typename E1, typename E2>
class ElementWiseScalarProd : public ElementWiseScalarExpression< ElementWiseScalarSum<E1, E2> >
{
public:
    ElementWiseScalarProd(E1&& lhs, E2&& rhs) : m_lhs(std::forward<E1>(lhs)), m_rhs(std::forward<E2>(rhs)) {}
...
private:
    expression_holder_t<E1> m_lhs;
    expression_holder_t<E2> m_rhs;
};

template<typename E1, typename E2> 
ElementWiseScalarProd<E1, E2> scalar_prod(E1 && lhs, E2 && rhs) {
    return ElementWiseScalarProd<E1, E2>(std::forward<E1>(lhs), std::forward<E2>(rhs));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM