下面的代码实现了一个非常简单的复数类型,根据语言的类型提升规则,在四个基本运算符(+,-,*和/)的作用下,具有不同字段的成员会自动为其基础字段提升(是其他complex<T>类型还是某些标量类型)。
这旨在作为一个整体示例,涵盖运算符重载以及模板的基本用法。
#include <type_traits> namespace not_std{ using std::decay_t; //---------------------------------------------------------------- // complex< value_t > //---------------------------------------------------------------- template<typename value_t> struct complex { value_t x; value_t y; complex &operator += (const value_t &x) { this->x += x; return *this; } complex &operator += (const complex &other) { this->x += other.x; this->y += other.y; return *this; } complex &operator -= (const value_t &x) { this->x -= x; return *this; } complex &operator -= (const complex &other) { this->x -= other.x; this->y -= other.y; return *this; } complex &operator *= (const value_t &s) { this->x *= s; this->y *= s; return *this; } complex &operator *= (const complex &other) { (*this) = (*this) * other; return *this; } complex &operator /= (const value_t &s) { this->x /= s; this->y /= s; return *this; } complex &operator /= (const complex &other) { (*this) = (*this) / other; return *this; } complex(const value_t &x, const value_t &y) : x{x} , y{y} {} template<typename other_value_t> explicit complex(const complex<other_value_t> &other) : x{static_cast<const value_t &>(other.x)} , y{static_cast<const value_t &>(other.y)} {} complex &operator = (const complex &) = default; complex &operator = (complex &&) = default; complex(const complex &) = default; complex(complex &&) = default; complex() = default; }; // 绝对值平方 template<typename value_t> value_t absqr(const complex<value_t> &z) { return z.x*z.x + z.y*z.y; } //---------------------------------------------------------------- // 运算符-(取反) //---------------------------------------------------------------- template<typename value_t> complex<value_t> operator - (const complex<value_t> &z) { return {-z.x, -z.y}; } //---------------------------------------------------------------- // 运算符+ //---------------------------------------------------------------- template<typename left_t,typename right_t> auto operator + (const complex<left_t> &a, const complex<right_t> &b) -> complex<decay_t<decltype(a.x + b.x)>> { return{a.x + b.x,a.y+ b.y}; } template<typename left_t,typename right_t> auto operator + (const left_t &a, const complex<right_t> &b) -> complex<decay_t<decltype(a + b.x)>> { return{a + b.x, b.y}; } template<typename left_t,typename right_t> auto operator + (const complex<left_t> &a, const right_t &b) -> complex<decay_t<decltype(a.x + b)>> { return{a.x + b, a.y}; } //---------------------------------------------------------------- // 运算符- //---------------------------------------------------------------- template<typename left_t,typename right_t> auto operator - (const complex<left_t> &a, const complex<right_t> &b) -> complex<decay_t<decltype(a.x - b.x)>> { return{a.x - b.x,a.y- b.y}; } template<typename left_t,typename right_t> auto operator - (const left_t &a, const complex<right_t> &b) -> complex<decay_t<decltype(a - b.x)>> { return{a - b.x, - b.y}; } template<typename left_t,typename right_t> auto operator - (const complex<left_t> &a, const right_t &b) -> complex<decay_t<decltype(a.x - b)>> { return{a.x - b, a.y}; } //---------------------------------------------------------------- // 运算符* //---------------------------------------------------------------- template<typename left_t, typename right_t> auto operator * (const complex<left_t> &a, const complex<right_t> &b) -> complex<decay_t<decltype(a.x * b.x)>> { return { a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x }; } template<typename left_t, typename right_t> auto operator * (const left_t &a, const complex<right_t> &b) -> complex<decay_t<decltype(a * b.x)>> { return {a * b.x, a * b.y}; } template<typename left_t, typename right_t> auto operator * (const complex<left_t> &a, const right_t &b) -> complex<decay_t<decltype(a.x * b)>> { return {a.x * b,a.y* b}; } //---------------------------------------------------------------- // 运算子/ //---------------------------------------------------------------- template<typename left_t, typename right_t> auto operator / (const complex<left_t> &a, const complex<right_t> &b) -> complex<decay_t<decltype(a.x / b.x)>> { const auto r = absqr(b); return { ( a.x*b.x + a.y*b.y) / r, (-a.x*b.y + a.y*b.x) / r }; } template<typename left_t, typename right_t> auto operator / (const left_t &a, const complex<right_t> &b) -> complex<decay_t<decltype(a / b.x)>> { const auto s = a/absqr(b); return { b.x* s, -b.y * s }; } template<typename left_t, typename right_t> auto operator / (const complex<left_t> &a, const right_t &b) -> complex<decay_t<decltype(a.x / b)>> { return {a.x / b,a.y/ b}; } }// 命名空间not_std int main(int argc, char **argv) { using namespace not_std; complex<float> fz{4.0f, 1.0f}; // makes a complex<double> auto dz = fz * 1.0; // still a complex<double> auto idz = 1.0f/dz; // also a complex<double> auto one = dz * idz; // a complex<double> again auto one_again = fz * idz; // 运算符测试,只是为了确保所有内容都能编译。 complex<float> a{1.0f, -2.0f}; complex<double> b{3.0, -4.0}; // All of these are complex<double> auto c0 = a + b; auto c1 = a - b; auto c2 = a * b; auto c3 = a / b; // All of these are complex<float> auto d0 = a + 1; auto d1 = 1 + a; auto d2 = a - 1; auto d3 = 1 - a; auto d4 = a * 1; auto d5 = 1 * a; auto d6 = a / 1; auto d7 = 1 / a; // All of these are complex<double> auto e0 = b + 1; auto e1 = 1 + b; auto e2 = b - 1; auto e3 = 1 - b; auto e4 = b * 1; auto e5 = 1 * b; auto e6 = b / 1; auto e7 = 1 / b; return 0; }