111

(注意: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);
}

(从传递的参数 中进行tie引用。)tupleT&


编辑:@DeadMG 提出的私下继承的建议tuple不错,但也有不少缺点:

  • 如果运营商是独立的(可能是朋友),我需要公开继承
  • 通过强制转换,我的函数/运算符(operator=特别是)可以很容易地被绕过
  • 使用该tie解决方案,如果某些成员对订购无关紧要,我可以忽略它们

我需要考虑此实现中的任何缺点吗?

4

4 回答 4

66

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

于 2011-06-02T19:07:04.757 回答
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...);
  }
}

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

bool lexiLessthan()
{
  return false;
}

现在您的示例变为:

return lexiLessthan(
    lhs.one_member, rhs.one_member, 
    lhs.another, rhs.another, 
    lhs.yet_more, rhs.yet_more
);
于 2013-05-10T07:37:53.583 回答
3

在我看来,您仍然没有解决与解决方案相同的问题std::tuple- 即,您必须知道每个成员变量的数量和名称,您在函数中复制了两次。你可以选择private继承。

struct somestruct : private std::tuple<...> {
    T& GetSomeVariable() { ... }
    // etc
};

这种方法一开始有点混乱,但您只是在一个地方维护变量和名称,而不是在每个地方为您希望重载的每个运算符维护。

于 2011-06-02T19:13:31.263 回答
1

如果您计划使用多个运算符重载或元组中的多个方法,我建议将元组作为类的成员或从元组派生。否则,您正在做的工作更多。在两者之间做出决定时,要回答的一个重要问题是:你希望你的类成为一个元组吗?如果不是,我建议包含一个元组并使用委托来限制接口。

您可以创建访问器来“重命名”元组的成员。

于 2011-06-02T19:51:17.513 回答