C++能否在同一运算符重载函数中批量实现多个运算符的重载
关于多运算符批量重载的实现方案
标准C原生语法不支持你设想的“将运算符作为模板形参、通过一个函数模板批量重载多个运算符”的写法。C的模板形参仅支持类型、合法的非类型常量(整数、指针、引用等),运算符本身不属于可作为模板参数的实体,不存在
template<operator O>这种合法语法。
但完全可以通过通用逻辑抽取、批量代码生成的方式,把十几份高度重复的重载代码压缩到十几行以内,彻底消除重复劳动。
第一步:抽取公共运算逻辑
你所有重复的运算符本质上都是对结构体的x、y两个成员执行同一个二元操作,完全可以把“逐成员执行运算、返回新结构体”这个公共逻辑封装成通用模板,所有运算符都复用这个逻辑,不需要每个重载都写一遍逐字段的代码:
// 通用二元运算辅助:执行op操作,从lhs、rhs取对应成员,返回指定类型的新实例 template<typename ResultT, typename OpT, typename LhsT, typename RhsT> ResultT apply_binary_op(OpT op, const LhsT& lhs, const RhsT& rhs) { return ResultT{ op(lhs.x, rhs.x), op(lhs.y, rhs.y) }; } // 通用复合赋值运算辅助:执行op操作,直接修改self的对应成员 template<typename OpT, typename SelfT, typename RhsT> SelfT& apply_binary_assign_op(OpT op, SelfT& self, const RhsT& rhs) { op(self.x, rhs.x); op(self.y, rhs.y); return self; }
第二步:编写轻量化的运算符重载
基于上面的辅助函数,每个运算符的实现都只需要一行,不需要重复编写成员访问逻辑:
// Point(int成员)的同类运算 Point operator+(const Point& a, const Point& b) { return apply_binary_op<Point>(std::plus<int>{}, a, b); } Point operator-(const Point& a, const Point& b) { return apply_binary_op<Point>(std::minus<int>{}, a, b); } // Point和int标量的运算 Point operator*(const Point& a, int scalar) { return apply_binary_op<Point>(std::multiplies<int>{}, a, Point{scalar, scalar}); } // Pointf(float成员)的同类运算 Pointf operator+(const Pointf& a, const Pointf& b) { return apply_binary_op<Pointf>(std::plus<float>{}, a, b); } // 跨类型运算(Point和Pointf混合) Pointf operator+(const Point& a, const Pointf& b) { return apply_binary_op<Pointf>(std::plus<float>{}, Pointf{static_cast<float>(a.x), static_cast<float>(a.y)}, b); } // 复合赋值运算符 Point& operator+=(Point& a, const Point& b) { return apply_binary_assign_op([](int& l, int r){ l += r; }, a, b); } Pointf& operator*=(Pointf& a, float scalar) { return apply_binary_assign_op([](float& l, float r){ l *= r; }, a, Pointf{scalar, scalar}); }
第三步:进一步批量消除重复
如果觉得逐行写运算符仍然繁琐,可以用宏批量生成所有需要的重载,达到接近“一套逻辑覆盖所有运算符”的效果:
// 批量生成宏:为目标类型T、对应成员基础类型BaseT,生成全部算术类运算符 #define GENERATE_ARITHMETIC_OPS(T, BaseT) \ T operator+(const T& a, const T& b) { \ return apply_binary_op<T>(std::plus<BaseT>{}, a, b); \ } \ T operator-(const T& a, const T& b) { \ return apply_binary_op<T>(std::minus<BaseT>{}, a, b); \ } \ T operator*(const T& a, BaseT scalar) { \ return apply_binary_op<T>(std::multiplies<BaseT>{}, a, T{scalar, scalar}); \ } \ T operator/(const T& a, BaseT scalar) { \ return apply_binary_op<T>(std::divides<BaseT>{}, a, T{scalar, scalar}); \ } \ T& operator+=(T& a, const T& b) { \ return apply_binary_assign_op([](BaseT& l, BaseT r){ l += r; }, a, b); \ } \ T& operator-=(T& a, const T& b) { \ return apply_binary_assign_op([](BaseT& l, BaseT r){ l -= r; }, a, b); \ } \ T& operator*=(T& a, BaseT scalar) { \ return apply_binary_assign_op([](BaseT& l, BaseT r){ l *= r; }, a, T{scalar, scalar}); \ } \ T& operator/=(T& a, BaseT scalar) { \ return apply_binary_assign_op([](BaseT& l, BaseT r){ l /= r; }, a, T{scalar, scalar}); \ } // 一行生成Point、Pointf需要的全部同类运算符 GENERATE_ARITHMETIC_OPS(Point, int) GENERATE_ARITHMETIC_OPS(Pointf, float)
对于跨类型的混合运算,只需要单独写几行带类型转换的重载即可,同样复用通用辅助函数,不需要重复实现逐字段的运算逻辑。
内容的提问来源于stack exchange,提问作者eitan 03
相关产品推荐
相关产品推荐

