可能重复:
Implementing comparision operators via 'tuple' and 'tie', a good idea?
有时我需要写一些丑陋的仿函数 e.g。
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以避免复制对象。
并感谢指出重复的问题
答案 0 :(得分:12)
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
生成 rvalue references 的元组。
答案 1 :(得分:0)
你可能最好使用tie而不是make_tuple(取决于是否值得避免成员的复制/移动),但除此之外,这将有效,并且没有什么可怕的。
如果你考虑一下,许多POD结构基本上是“命名元组”,而C ++实际上通过提供成员之间的平等比较(以及复制,移动等)来满足这一要求 - 并且在大多数情况下,扩展它(词典)由成员少于比较也是有道理的。但不幸的是,C ++没有提供任何方法来指定成员的词典比较,除非明确地写出来。当然,在具有内省的语言中,添加它会非常容易,但在C ++中,它并非如此。
一个明显的答案是实际上让你的类实际上是一个命名元组。而不是让成员int date_,int64_t time_和string id_,从元组继承,并写入隐藏用户的元组的访问器方法。但是在这种情况下,你刚刚在访问器实现中的丑陋的比较实现中进行了丑陋交易,并且不清楚是否更好。
你可以用宏来结束丑陋,但这可能不是更好:
DEFINE_NAMED_TUPLE_CLASS(MyDate, int date, int64_t time, string id)
...
END_NAMED_TUPLE_CLASS
或者您可以构建自己的外部代码生成器,允许您预处理具有“named_tuple_class”的扩展C ++,只需将标记更改为“class”然后定义比较运算符即可处理。但这是很多工作。