operator+= 在自定义复杂类型和 std::complex 之间
operator+= between custom complex type and 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();
}
编译器无法推断调用哪个 operator+= 并且 returns 出现以下错误
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;
| ^
有没有办法解决这个问题?
+=
的自定义运算符适用于您的示例:
[[maybe_unused]] constexpr static inline std::complex<double> operator+=(
const std::complex<double>& lhs,
const CpxScalar& rhs) noexcept {
return lhs + rhs.eval();
}
为运算符提供您自己的重载是可行的方法。
但是,有几点需要牢记:
既然你已经有了一个演员表,你所要做的就是使用它,让常规操作员从那里拿走它。
既然要“伪装”为 std::complex
的类型是 CpxScalarExpression<Expr>
,那么它应该是重载操作的类型。
std::complex
的 operator+=()
通常允许您将不同类型的复数相加,因此我们应该保持这一点。这意味着运算符应该根据传入的 std::complex
的组件类型进行模板化。
我们需要确保 return 完全 std::complex
的 operator+=
想要 return.使用 decltype(auto)
作为重载的 return 类型可为您提供。
将所有这些放在一起,我们降落在:
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+=()
.
相同的功能
我希望我的自定义复杂类型能够与 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();
}
编译器无法推断调用哪个 operator+= 并且 returns 出现以下错误
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;
| ^
有没有办法解决这个问题?
+=
的自定义运算符适用于您的示例:
[[maybe_unused]] constexpr static inline std::complex<double> operator+=(
const std::complex<double>& lhs,
const CpxScalar& rhs) noexcept {
return lhs + rhs.eval();
}
为运算符提供您自己的重载是可行的方法。
但是,有几点需要牢记:
既然你已经有了一个演员表,你所要做的就是使用它,让常规操作员从那里拿走它。
既然要“伪装”为
std::complex
的类型是CpxScalarExpression<Expr>
,那么它应该是重载操作的类型。std::complex
的operator+=()
通常允许您将不同类型的复数相加,因此我们应该保持这一点。这意味着运算符应该根据传入的std::complex
的组件类型进行模板化。我们需要确保 return 完全
std::complex
的operator+=
想要 return.使用decltype(auto)
作为重载的 return 类型可为您提供。
将所有这些放在一起,我们降落在:
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+=()
.