使用make_tuple进行比较

时间:2012-05-29 20:14:24

标签: c++ c++11 tuples idioms

  

可能重复:
  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以避免复制对象。
并感谢指出重复的问题

2 个答案:

答案 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”然后定义比较运算符即可处理。但这是很多工作。