在使用表达模板的矩阵库中实现一个行类别的分配运算符

Implementing an assignment operator for a row class in a matrix library which uses expression templates

本文关键字:一个 运算符 分配 实现      更新时间:2023-10-16

假设我们有一个matrix类,该类使用表达模板,以便使用代理对象使编译器可以优化化合物表达式。

现在,创建以下形式的row类是很自然的:

namespace detail
{
    template<class E>
    class row
        : public vector_expression<row<E>>
    {
    public:
        using size_type = size_type_t<E>;
        template<class F>
        row(F&& e, size_type i)
            : m_e(std::forward<F>(e)),
              m_i(i)
        {}
        result_of_call_operator_t<E&> operator()(size_type j) { return m_e(m_i, j); }
        result_of_call_operator_t<E const&> operator()(size_type j) const { return m_e(m_i, j); }
    private:
        E m_e;
        size_type const m_i;
    };
}

和以下形式的相应辅助功能:

template<class E, class =
    std::enable_if_t<detail::is_matrix_expression_v<E>>>
detail::row<E> row(E&& e, detail::size_type_t<E> i) {
    return { std::forward<E>(e), i };
}

这个想法是row可能是实际matrix对象的行或(时间(matrix_expression

我现在想做的是将row配备给分配操作员,以便我们可以将(兼容(vector_expression s分配给row。当然,如果row对象的相关matrix_expression不是"可分配"。

,则应禁用这样的操作员。

这是有用类型特征的第一个想法:

template<class E, class F>
using is_assignable_t = decltype(std::declval<result_of_call_operator_t<E>>() = std::declval<result_of_call_operator_t<F>>());
template<class E, class F>
constexpr bool is_assignable_v = is_detected_v<is_assignable_t, E, F>;

现在,问题在于我们可能有一个column类和许多类似的类。因此,我正在寻找一种以上述方式实现上述想法的方法,这并不迫使我在这些类中添加作业运算符。

确切地说,我可以为row配备以下操作:

template<class F,
    class = std::enable_if_t<is_assignable_v<E&, F>>>
row& operator=(vector_expression<F> const& e)
{
    /* ... */
    return *this;
}

但是,我也需要在column类中添加此类运算符和此类其他类别。

总而言之,我想在vector_expression级别上实现此目标,以便可以将"兼容"(即元素转换(vector_expression分配给"可分配"(在上述意义上(vector_expression。我们该怎么做?

我已经掌握了上面的实现详细信息,但这是您需要回答我问题的东西的实时演示。

在成员类numeric::detail::row中,已经定义的元素(m_e(和索引(m_i(,然后是我的代码:

        template<class F,
            class = std::enable_if_t<is_assignable_v<E&, F>>>
            row& operator=(vector_expression<F> const& e)
        {
            for (size_type i = 0; i < m_e.row_size(); ++i)
            {
                m_e(m_i, i) = e(i);
            }
            return *this;
        }