c++中STL中tuple类的运算符重载
头文件:
#include<tuple>
总结
tuple类中重载了
“==”, “!=”, “>”, “>=”, “<”, “<=”
等比较运算操作符,但实现都是靠
“==“和”<”
而这两个运算符的实现是通过递归的方法依次比较tuple类对象中的元素。
所以tuple类中的元素只需重载"<“和”=="即可实现所有运算符的重载。
详解:
主要注意源代码中的 “==” 和 “<” 重载,这也是STL中的主要运算符。
其余运算符通过调用这两个运算符得到。
STL中源代码(粗略浏览重载的操作符和汉字注释即可)
// OPERATORS FOR tuple
template <class... _Types1, class... _Types2>
_NODISCARD constexpr bool operator==(const tuple<_Types1...>& _Left, const tuple<_Types2...>& _Right) {
static_assert(sizeof...(_Types1) == sizeof...(_Types2), "cannot compare tuples of different sizes");
//错误警示,若两个tuple函数的规格不一,assert函数会向stderr端传入"cannot compare tuples of different sizes",报错
return _Left._Equals(_Right);
//_Equal是tuple类的成员函数,操作符重载的重点,注意!一会探究
}
template <class... _Types1, class... _Types2>
_NODISCARD constexpr bool operator!=(const tuple<_Types1...>& _Left, const tuple<_Types2...>& _Right) {
return !(_Left == _Right);
//间接调用==,不必深究
}
template <class... _Types1, class... _Types2>
_NODISCARD constexpr bool operator<(const tuple<_Types1...>& _Left, const tuple<_Types2...>& _Right) {
static_assert(sizeof...(_Types1) == sizeof...(_Types2), "cannot compare tuples of different sizes");
//错误警示,若两个tuple函数的规格不一,assert函数会向stderr端传入"cannot compare tuples of different sizes",报错
return _Left._Less(_Right);
//_Less是tuple类的成员函数,也是操作符重载的关键
}
template <class... _Types1, class... _Types2>
_NODISCARD constexpr bool operator>=(const tuple<_Types1...>& _Left, const tuple<_Types2...>& _Right) {
return !(_Left < _Right);
//调用<
}
template <class... _Types1, class... _Types2>
_NODISCARD constexpr bool operator>(const tuple<_Types1...>& _Left, const tuple<_Types2...>& _Right) {
return _Right < _Left;
//调用<
}
template <class... _Types1, class... _Types2>
_NODISCARD constexpr bool operator<=(const tuple<_Types1...>& _Left, const tuple<_Types2...>& _Right) {
return !(_Right < _Left);
//调用<
}
}
tuple类中重载了 “==”, “!=”, “>”, “>=”, “<”, “<=” 等比较运算操作符
但从代码上面可以看出,其中主要重载了"==", "<"这两个运算符,
其他操作符通过调用这两个运算符得出答案。
而这两个操作符重载的关键在于:_Less()和_Equals()。
通过调用方式可以得出这是tuple类中的成员函数。
继续查看源代码:
template <class... _Other>
constexpr bool _Equals(const tuple<_Other...>& _Right) const {
return _Myfirst._Val == _Right._Myfirst._Val && _Mybase::_Equals(_Right._Get_rest());
}
template <class... _Other>
constexpr bool _Less(const tuple<_Other...>& _Right) const {
return _Myfirst._Val < _Right._Myfirst._Val
|| (!(_Right._Myfirst._Val < _Myfirst._Val) && _Mybase::_Less(_Right._Get_rest()));
}
明显有递归调用,以_Equal为例,探究成员函数运算过程:
return _Myfirst._Val == _Right._Myfirst._Val && _Mybase::_Equals(_Right._Get_rest());
先说题外话:
Tuple的实现原理:tuple类是通过递归实现。
如要建立tuple类的一个对象,名为temp
tuple<int, string, double> temp;
则它是先建立一个tuple类:base
tuple<> base
再以之前的base类为基础,建立新的tuple类,继续命名为base
tuple<double> base
继续以之前的base类为基础,建立新的tuple类,命名为base
tuple<string, double> base
最后以名为base的tuple类建立目标类
tuple<int, string, double> temp;
具体可以百度tuple实现原理,
大意就是每个tuple中都有去掉首元素后其余元素的tuple类对象:base
比如:
tuple<int,string,double> one//此对象中有一个成员变量:tuple<string, double> base
tuple<int,double, char> two//此对象中有一个成员变量:tuple<string, char> base
tuple<int, int, int> three//此对象中有一个成员变量:tuple<int, int> base
回到主题:
return _Myfirst._Val == _Right._Myfirst._Val && _Mybase::_Equals(_Right._Get_rest());
_Myfirst.val是当前tuple类的对象中第一个元素的值。
_Get_rest()返回当前tuple类对象中的base类,也就是除去第一个元素后剩下的元素构成的tuple类的对象。
这是比较第一个元素是否相等
_Myfirst._Val == _Right._Myfirst._Val
这就相当于继续比较剩下的元素是否相等,继续调用Equal,是一个递归算法
_Mybase::_Equals(_Right._Get_rest());
将结果用&&结合,再return
return _Myfirst._Val == _Right._Myfirst._Val && _Mybase::_Equals(_Right._Get_rest());
这就是_Equal函数的运算过程。
_Less同理。