使用make_tuple进行比较
using make_tuple for comparison
可能的重复项:
通过"元组"和"领带"实现比较运算符,一个好主意?
有时我需要写一些丑陋的函子
例如
lhs.date_ < rhs.date_ ||
lhs.date_ == rhs.date_ && lhs.time_ < rhs.time_ ||
lhs.date_ == rhs.date_ && lhs.time_ == rhs.time_ && lhs.id_ < rhs.id_ .....
这真的让我很恼火。
所以我开始避免这样写:
std::make_tuple( lhs.date_, lhs.time_, lhs.id_ ) <
std::make_tuple(rhs.date_, rhs.time_, rhs.id_ );
我几乎很高兴,但请注意,我可能不是出于元组的目的使用元组,这让我担心。
你能批评这个解决方案吗?
还是一个好习惯?
你如何避免这样的比较?
更新:
感谢您指向 std::tie 以避免复制对象。
并感谢您指出重复的问题
std::tuple
比较运算符的声明指出:
按字典顺序比较 lhs 和 rhs,即比较第一个元素(如果它们是等效的),则比较第二个元素,如果它们是等效的,则比较第三个元素,依此类推。
因此,您正在做的事情,除了有可能创建不需要的临时(可能经过优化)之外,对我来说似乎还可以。
请注意,等价意味着!( lhs < rhs ) && !( rhs < lhs )
而不是lhs == rhs
,这就是相等。假设等价和相等对你的类意味着相同,这没关系。请注意,这与例如通过密钥访问set
/map
没有什么不同。
为了避免临时性,您可以使用std::tie
,它对其参数进行左值引用元组:
std::tie( lhs.date_, lhs.time_, lhs.id_ ) <
std::tie( rhs.date_, rhs.time_, rhs.id_ );
以类似的方式,std::forward_as_tuple
创建右值引用的元组。
您可能最好使用 tie 而不是 make_tuple(取决于是否值得避免复制/移动成员),但除此之外,这将起作用,并且没有什么可怕的。
如果你考虑一下,许多 POD 结构基本上是"命名元组",C++实际上通过提供按成员相等比较(以及复制、移动等)来满足这一点。——在大多数情况下,将其扩展到(词典编纂)按成员小于比较也是有意义的。但不幸的是,C++没有提供任何方法来指定成员的字典顺序比较,除非明确写出来。当然,在具有内省功能的语言中,添加起来很容易,但在C++中,它不是。
一个显而易见的答案是实际上使您的类实际上是一个命名元组。而不是让成员 int date_、int64_t time_ 和字符串id_,而是从元组继承,并编写对用户隐藏元组的访问器方法。但是在这种情况下,您只是将比较实现中的丑陋换成了访问器实现中的丑陋,并且不清楚这是否更好。
你可以使用宏来包装丑陋,但这可能不是更好:
DEFINE_NAMED_TUPLE_CLASS(MyDate, int date, int64_t time, string id)
...
END_NAMED_TUPLE_CLASS
或者,您可以构建自己的外部代码生成器,该生成器允许您预处理具有"named_tuple_class"的扩展C++,它只需将标记更改为"class",然后定义比较运算符即可处理该。但这是很多工作。
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么比较运算符如此快速
- Cpp-Tuple使用带有变量的get
- 我可以使用 g++ 进行三种比较 (<=>) 吗?
- 比较字符数组
- 将模板化的类型与C++中的某些类/类型进行比较
- C++自定义比较函数
- 如何比较自定义类的std::变体
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- std::设置自定义比较器
- 布尔比较运算符是如何在C++中工作的
- C++将目录中的所有文件与::filesystem进行比较
- shell排序中的交换和比较
- 如何在C++中比较两个char数组
- catch框架有没有办法比较流或文件
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 智能指针作为无序映射键,并通过引用进行比较
- 比较if语句中的数组值和int值
- 对于循环变体比较
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题