通过“tuple”和“tie”来实现比较运算符,这是一个好主意吗?
(注: tuple
和tie
可以从Boost或C ++ 11中取得)
在编写只有两个元素的小型结构时,我有时会倾向于select一个std::pair
,因为所有重要的东西都已经为该数据types完成了,比如operator<
for strict-weak-ordering。
缺点虽然是几乎没用的variables名称。 即使我自己创build了typedef
,两天之后我也不会记得first
和second
是什么,特别是如果它们是同一types的话。 这对于两个以上的成员来说更糟,因为嵌套pair
非常糟糕。
另一种select是从Boost或C ++ 11中得到一个tuple
,但是看起来并没有更好更清晰。 所以我回到自己编写结构,包括任何需要的比较运算符。
由于特别是operator<
可能相当麻烦,所以我想通过仅仅依赖于为tuple
定义的操作来规避这个混乱:
operator<
例如严格弱sorting的例子:
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
从所传递的参数构成T&
引用。)
编辑 :从@DeadMG私人从tuple
inheritance的build议不是一个坏的,但它有一些缺点:
- 如果运营商是独立的(可能是朋友),我需要公开inheritance
- 通过投射,我的function/操作员(特别是
operator=
)可以轻松绕过 - 有了这个
tie
解决scheme,如果他们对订购无关紧要,我可以省略某些成员
这个实现有什么缺点,我需要考虑吗?
这肯定会使编写一个正确的操作符比自己滚动它更容易。 如果分析显示比较操作是您的应用程序的一个耗时部分,我会说只考虑一种不同的方法。 否则,维护这一点的难度将超过任何可能的性能问题。
我遇到了同样的问题,我的解决scheme使用c ++ 11 variadic模板。 代码如下:
.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 );
在我看来,你仍然没有解决std::tuple
解决的问题 – 即你必须知道每个成员variables的名字和数量,你需要在函数中重复两次。 你可以selectprivate
inheritance。
struct somestruct : private std::tuple<...> { T& GetSomeVariable() { ... } // etc };
这种方法稍微有些乱七八糟,但是你只是把variables和名字保存在一个地方,而不是每个你想要过载的操作符的地方。
如果你打算使用多个运算符重载或者更多的元组方法,我build议把元组作为类的一个成员,或者从元组派生出来。 否则,你在做什么是更多的工作。 在决定两者之间时,一个重要的问题就是:你想让你的class级成为一个元组吗? 如果不是,我会build议包含一个元组,并通过使用委托来限制接口。
您可以创build访问器来“重命名”元组的成员。