实现比较运算符的模板类
Template class implementing comparison operators
将所有重载比较操作符写入一个类中是我的一个经常任务,因此我编写了一个模板类来实现<,<=,>=,!=如果派生类实现了==和<它是工作的,但特点是大量的转换和不那么明显的"奇怪的反复出现的模板模式",所以我想知道是否有更简单的解决方案?>
template <class Derived>
class Comparable
{
public:
bool operator!=(const Comparable<Derived>& other) {
return !(static_cast<Derived*>(this)->operator==
(*static_cast<const Derived*>(&other)));
}
bool operator<=(const Comparable<Derived>& other) {
return (static_cast<Derived*>(this)->operator==
(*static_cast<const Derived*>(&other)))
|| (static_cast<Derived*>(this)->operator<
(*static_cast<const Derived*>(&other)));
}
bool operator>(const Comparable<Derived>& other) {
return !(static_cast<Derived*>(this)->operator==
(*static_cast<const Derived*>(&other)))
&& !(static_cast<Derived*>(this)->operator<
(*static_cast<const Derived*>(&other)));
}
bool operator>=(const Comparable<Derived>& other) {
return !(static_cast<Derived*>(this)->operator<
(*static_cast<const Derived*>(&other)));
}
};
如果从注释中的描述中不明显:
template <typename T>
struct Comparable {
friend bool operator!=(T const & lhs, T const & rhs) { return !(lhs == rhs); }
friend bool operator> (T const & lhs, T const & rhs) { return rhs < lhs; }
// ...
};
class MyType : Comparable<MyType> {
int data;
friend bool operator==(MyType const & lhs, MyType const & rhs) {
return lhs.data == rhs.data;
}
friend bool operator< (MyType const & lhs, MyType const & rhs) {
return lhs.data < rhs.data;
}
public:
// ...
};
当编译器遇到MyType a, b; a > b;
查找操作符时,最终将执行ADL,这将查看MyType
和Comparable<MyType>
(因为这是一个基数),在那里它将找到您需要的实现:bool operator>(MyType const&, MyType const&)
。
作为自由函数的操作符允许定义在被比较的类型之外(在本例中是基类),同时使这些操作符只能通过ADL可用(两个实参之一必须是Comparable<MyType>
)。自由函数的使用还提供了类型对称,编译器将允许在两侧进行隐式转换,而对于成员函数,它只允许在操作符的右侧进行转换。
为了完整起见,可以采用另一种技巧,即在名称空间中提供操作符作为模板,并提供一个标记,用于将该名称空间引入ADL:
namespace operators {
template <typename T>
bool operator>(T const & lhs, T const & rhs) {
return rhs < lhs;
}
// rest of the operators come here
struct tag {};
}
class MyType : operators::tag {
int data;
friend bool operator<(T const & lhs, T const & rhs) {
return lhs.data < rhs.data;
}
//...
};
的技巧基本相同,只是在这种情况下,操作符不在基类中找到,而是在与基类相关联的名称空间中找到。这个解决方案比前一个稍微差一些,因为它对不同形式的误用是开放的,包括using namespace operators;
,它将使所有类型的模板化操作符可用。
相关文章:
- 为什么比较运算符如此快速
- 布尔比较运算符是如何在C++中工作的
- 关于 std::min, std::max 中的比较运算符的混淆
- 三向比较运算符成员与非成员实现
- 标准::可选枚举的比较运算符
- C++分数混合比较运算符错误
- 不能将重载比较运算符与 Catch 测试一起使用
- 重构使用动态强制转换的 std::set 的比较运算符
- 为什么我的比较运算符不比较我的点长和双精度值?
- 高效简单的结构比较运算符
- 如何实现 Boost.Hana 结构的相等比较运算符?
- 为什么sub_match和basic_string比较运算符使用额外的字符串副本实现?
- 是否可以在C++中使用三元运算符在 if 语句中选择比较运算符?
- 在priority_queue的自定义类中重载比较运算符
- 为什么C++容器之间存在比较运算符
- 尝试使用比较运算符对对象向量进行排序
- C++复合逻辑运算符不使用比较运算符
- C++:比较运算符>和字符串文本的意外结果
- 重载对象成员的比较运算符
- 比较运算符==中的对象指针