Реализация оператора присваивания для класса строк в матричной библиотеке, которая использует шаблоны выражений
Предположим, у нас есть 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
сrow
, Конечно, такой оператор должен быть отключен, еслиmatrix_expression
изrow
объект не "присваивается".
Вот первая идея для полезной черты типа:
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
, Как мы можем сделать это?
Я скрыл подробности реализации выше, но здесь есть живая демонстрация того, что вам нужно, чтобы ответить на мой вопрос.
1 ответ
В классе участника 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;
}