通过'tuple'和'tie'实现比较运算符,这是一个好主意?

Xeo*_*Xeo 94 c++ tuples operators c++11 strict-weak-ordering

(注意:tuple并且tie可以从Boost或C++ 11中获取.)
当编写只包含两个元素的小结构时,我有时倾向于选择a std::pair,因为所有重要的东西都已经为该数据类型完成,例如operator<严格弱序.
但缺点是几乎没用的变量名.即使我自己创造了这个typedef,我也不会记得2天后究竟是什么first,second究竟是什么,特别是如果它们都属于同一类型.这对两个以上的成员来说更糟糕,因为嵌套pair非常糟糕.
另一种选择是tuple,无论是来自Boost还是C++ 11,但它看起来并没有更好,更清晰.所以我回去自己编写结构,包括任何需要的比较运算符.
特别是因为这operator<可能非常繁琐,我想通过依赖为tuple以下定义的操作来绕过这整个混乱:

示例operator<,例如严格弱排序:

bool operator<(MyStruct const& lhs, MyStruct const& rhs){
  return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
         std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}
Run Code Online (Sandbox Code Playgroud)

(从传递的参数中引用tie一个引用.) tupleT&


编辑:从@DeadMG到私有继承的建议tuple并不是很糟糕,但它有一些缺点:

  • 如果运营商是独立的(可能是朋友),我需要公开继承
  • 通过铸造,我的功能/操作员(operator=特别是)可以轻松绕过
  • 有了这个tie解决方案,如果他们对订购无关紧要,我可以省略某些成员

我需要考虑这个实现有什么缺点吗?

Mar*_*k B 58

这肯定会使编写正确的运算符比自己滚动更容易.我要说的是,如果分析显示比较操作是应用程序的一个耗时部分,则只考虑不同的方法.否则,维护这一点的容易程度应该超过任何可能的性能问题.

  • 我有一次完全相同的想法,并做了一些实验.看到编译器内联并优化了*与元组和引用有关的所有内容,发出的汇编几乎与手写代码完全相同,我们感到非常惊讶. (49认同)
  • 我无法想象`tuple <>`的`operator <`会慢于手写的那种情况. (17认同)
  • @JohannesD:我可以支持那个证词,做过同样的事 (7认同)

小智 5

我遇到了同样的问题,我的解决方案使用了c ++ 11可变参数模板.代码如下:

.h部分:

/***
 * Generic lexicographical less than comparator written with variadic templates
 * Usage:
 *   pass a list of arguments with the same type pair-wise, for intance
 *   lexiLessthan(3, 4, true, false, "hello", "world");
 */
bool lexiLessthan();

template<typename T, typename... Args>
bool lexiLessthan(const T &first, const T &second, Args... rest)
{
  if (first != second)
  {
    return first < second;
  }
  else
  {
    return lexiLessthan(rest...);
  }
}
Run Code Online (Sandbox Code Playgroud)

没有参数的基本情况的.cpp:

bool lexiLessthan()
{
  return false;
}
Run Code Online (Sandbox Code Playgroud)

现在你的例子变成:

return lexiLessthan(
    lhs.one_member, rhs.one_member, 
    lhs.another, rhs.another, 
    lhs.yet_more, rhs.yet_more
);
Run Code Online (Sandbox Code Playgroud)