GOOGLE ADS

четверг, 28 апреля 2022 г.

оператор += между пользовательским сложным типом и std::complex

Я хочу, чтобы мой пользовательский сложный тип мог взаимодействовать с std::complex, но в некоторых случаях компилятор не преобразует мой тип в std::complex.

Вот минимальный рабочий пример:

#include <complex>
#include <iostream>
template <typename Expr>
class CpxScalarExpression
{
public:
inline std::complex< double > eval() const { return static_cast<Expr const&>(*this).eval(); }

inline operator std::complex< double >() const { return static_cast<Expr const&>(*this).eval(); }
};
class CpxScalar: public CpxScalarExpression<CpxScalar>
{
public:
CpxScalar(): m_value(0) {}
CpxScalar(const double value): m_value(value) {}
CpxScalar(const double real_value, const double imag_value): m_value(real_value, imag_value) {}
CpxScalar(const std::complex< double > value): m_value(value) {}
template<typename Expr>
CpxScalar(const CpxScalarExpression< Expr >& expr): m_value(expr.eval()) {}
public:
inline std::complex< double > eval() const { return m_value; }
private:
std::complex< double > m_value;
};
int main()
{
CpxScalar a(10,-5);
//std::complex< double >* b = reinterpret_cast< std::complex< double >* >(&a);
std::complex< double > b = a;
b += a;

//std::cout << b->real() << " " << b->imag();
std::cout << b.real() << " " << b.imag();
}

Компилятор не может определить, какой оператор += вызывать, и возвращает следующую ошибку.

est.cpp:50:4: error: no match for 'operator+=' (operand types are 'std::complex<double>' and 'CpxScalar')
50 | b += a;
| ~~^~~~
In file included from test.cpp:1:
/usr/include/c++/9/complex:1287:7: note: candidate: 'std::complex<double>& std::complex<double>::operator+=(double)'
1287 | operator+=(double __d)
| ^~~~~~~~
/usr/include/c++/9/complex:1287:25: note: no known conversion for argument 1 from 'CpxScalar' to 'double'
1287 | operator+=(double __d)
| ~~~~~~~^~~
/usr/include/c++/9/complex:1329:9: note: candidate: 'template<class _Tp> std::complex<double>& std::complex<double>::operator+=(const std::complex<_Tp>&)'
1329 | operator+=(const complex<_Tp>& __z)
| ^~~~~~~~
/usr/include/c++/9/complex:1329:9: note: template argument deduction/substitution failed:
test.cpp:50:7: note: 'CpxScalar' is not derived from 'const std::complex<_Tp>'
50 | b += a;
| ^

Есть ли способ преодолеть эту проблему?


Решение проблемы

Предоставление собственной перегрузки для оператора — это путь.

Тем не менее, есть несколько вещей, о которых следует помнить:


  • Поскольку у вас уже есть бросок, все, что вам нужно сделать, это использовать его и позволить обычному оператору взять его оттуда.


  • Поскольку тип, предназначенный для «представления» как std::complexесть CpxScalarExpression<Expr>, должен быть тем, с которым работает перегрузка.


  • std::complex, operator+=()как правило, позволяет вам складывать сложные значения разных типов, поэтому мы должны поддерживать это. Это означает, что оператор должен быть шаблоном для входящего std::complexтипа компонентов.


  • Мы должны убедиться, что возвращаем именно то std::complex, что operator+=хочет вернуть. Использование decltype(auto)в качестве возвращаемого типа перегрузки дает вам именно это.



Собрав все это вместе, мы попадаем в:

template<typename T, typename Expr>
constexpr decltype(auto) operator+=(
std::complex<T>& lhs,
const CpxScalarExpression<Expr>& rhs) {
return lhs += std::complex<double>(rhs);
}

Добавление этого в опубликованный вами код заставляет его работать так, как ожидалось, и должно дать вам паритет функций std::complexс operator+=().

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...