C++奇技淫巧&黑科技 之 自定义二元操作符(二目运算符) user defined binary operator in C++
一、前言
1、缘起
很早之前,有看到boost中似乎有 a <oper> b
的实现。
可以用来实现类似于 1 <sum> 2 == 3
的效果,实在大开眼见。
遂当时花了一下午的时间特意研究并实现了这种效果,今天写出来与大家分享。
2、简介
众所周知,C++中我们可以重载绝大多数的运算符,比如我们时常用到的cin>>a>>b>>c;
,就是重载了operator>>
实现的。
但标准库并不支持我们定义新的运算符,比如我们没法定义 exp 为指数运算符来实现 2 exp 3 == 8
的效果。
所以为了达到a <oper> b
的效果 ,我们需要自己利用C++的特性来实现。
3、作用
研究时只是本着好玩好奇的心态,并没有考虑什么实际的用处。 (明明java连运算符都不能重载也活得好好的。)
假设我们定义两个向量a,b。
class Vector{
public:
double x,y;
}a,b;
①向量叉乘(cross)与点乘(dot)的传统写法
我们可以用它来实现 向量直观的叉乘(cross)和点乘(dot)。
通常来说我们只能使用 cross(a,b)
或 a.cross(b)
的方式来实现向量乘法。(当然你可以选择重载operator*
,但是向量有两种乘法,这样极其容易混淆。)
②使用自定义二元操作符的写法
我们可以使用 Vector c = a <cross> b , d = a <dot> b;
这样花里胡哨非常直觉简单明了的方式来表达。
二、简易实现
1、思路
看到a<b>c
这样的角括号格式,最先想到的是模板,但细想之后发现不能实现。
那么就只能是单独的小于和大于,那么只需要通过重载两个运算符就能实现这样的操作了。
2、简易实现 1 <sum> 2
①运算顺序
对于a<b>c
,大于小于运算优先级相同并且从左向右结合。
所以我们会先计算 a<b
的结果,在和c作大于运算(a<b)>c
。
②定义class Oper
为了实现 a <oper> b
的效果,我们必须要引入一个中间类别。
显然这个class应该具有两个成员变量,一个用来中转a,一个是定义a和b的二元运算。
struct Oper{
int t;
function<int(int,int)> func;
Oper(function<int(int,int)> func):func(func){
}
};
③重载大于小于
然后只需要简单地重载operator<
和operator>
就大功告成了。
Oper operator<(int a,Oper b){
b.t=a;
return b;
}
int operator>(Oper b,int c){
return b.func(b.t,c);
}
④完整代码
#include "bits/stdc++.h"
using namespace std;
struct Oper{
int t;
function<int(int,int)> func;
Oper