如何使set :: find()适用于自定义类对象?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使set :: find()适用于自定义类对象?相关的知识,希望对你有一定的参考价值。
我对使用STL set::find()
作为一组我自己定义的类对象感到困惑。
我的类包含两个以上的项目(3/4/5等),那么如何重载less
运算符?
我尝试了3变量,如下所示,工作正常:
return( (a1.i < a2.i) ||
(!(a1.i > a2.i) && (a1.f < a2.f)) ||
(!(a1.i > a2.i) && !(a1.f > a2.f) && (a1.c < a2.c)));
其中,a1
和a2
是类对象,(i
,f
和c
是班级成员)。
现在我想为n个成员推广这个,但是我的find()
并不总是有效。
我一直在查看STL的详细文档,试图了解set::find()
是如何实现的,以及为什么它需要更少(<
)运算符重载。
我提到了sgi和msdn文档,但我在那里找不到set::find()
的实现细节。
我的set::find()
实施中我做错了什么?
您必须定义对象的严格排序。因此,如果您的对象由n
成员a_1
... a_n
组成,所有这些都有严格的排序,您可以做的是:
bool operator< (const TYPE &rhs) {
if (a_1 < rhs.a_1) return true; else if (a_1 > rhs.a_1) return false;
if (a_2 < rhs.a_2) return true; else if (a_2 > rhs.a_2) return false;
...
if (a_n < rhs.a_n) return true;
return false;
}
编辑:如果你可以使用boost或C ++ 11,你应该选择Luc Danton在答案中建议的std::tie
/ boost::tie
方法。它更清洁。
您可以使用元组轻松获得成员的词典排序:
return std::tie(lhs.i, lhs.f, lhs.c) < std::tie(rhs.i, rhs.f, rhs.c);
这要求每个成员都具有可比较的类型,例如lhs.i < rhs.i
是有道理的。
请注意,std::tie
和std::tuple
仅适用于C ++ 11,因此对于C ++ 03,您可以使用例如提供boost::tie
的Boost.Tuple(boost::tuple
使用与std::tuple
相同的顺序)。
至于应该去哪里,习惯上把它放在operator<
(毕竟这是使tie
用于简单排序的原因)。这个操作员经常会成为朋友,所以这看起来像:
class foo {
public:
/* public interface goes here */
// declaration of non-member friend operator
// if it doesn't need to be a friend, this declaration isn't needed
friend
bool operator<(foo const& lhs, foo const& rhs);
private:
T t;
U u;
V v;
};
bool operator<(foo const& lhs, foo const& rhs)
{
// could be boost::tie
return std::tie(lhs.t, lhs.u, lhs.v) < std::tie(rhs.t, rhs.u, rhs.v);
}
正如你所看到的那样,它不是完全自动的,因为operator<
的实现需要列出foo
的每个成员(或者至少是那些对排序很重要的成员),两次。我害怕没有更好的方法。
而不是提供operator<
你可以专门为std::less
foo
,但这有点异国情调,而不是首选的方式。如果排序仍然没有意义成为foo
的扩展接口的一部分(例如,如果没有规范的可能有多个排序是有意义的),那么首选的方法是编写一个仿函数:
struct foo_ordering {
bool operator()(foo const& lhs, foo const& rhs) const
{
/* implementation as before, but access control/friendship
has to be planned for just like for operator< */
}
};
然后你会使用例如std::set<foo, foo_ordering>
。
请注意,无论排序采用何种形式(通过operator<
,std::less<foo>
或仿函数),如果它与std::set
或任何其他关联容器一起使用(默认情况下,例如std::set<T>
使用std::less<T>
,而operator<
默认使用foo
)它必须遵循一些严格的标准,即它必须是严格的弱序。但是,如果用于http://www.sgi.com/tech/stl/set.html排序的所有成员都有SW顺序,则生成的词典排序也是SW排序。
std :: set元素比较函数应该在元素域上定义Strict Weak Ordering关系。使用这个定义我们可以说如果compare(a,b)为false且compare(b,a)也为false,则两个元素是等价的。 std :: find可以使用这个假设来实现。
你可以在这里找到更多:http://www.sgi.com/tech/stl/StrictWeakOrdering.html和operator <
你的struct Data
{
bool operator < (const Data& right) const
{
return( (this.i < right.i) ||
(!(this.i > right.i) && (this.f < right.f)) ||
(!(this.i > right.i) && !(this.f > right.f) && (this.c < right.c)));
}
}
应该能够将每个对象与给定的对象进行比较,就像那样
this.i == right.i
此外,您的比较算法看起来很可疑,因为它不考虑情况,何时
this.f == right.f
要么
std::set
而你实际上不应该对the website of SGI实现感兴趣。它可以从编译器更改为编译器,并且可以在将来进行修改。您的程序应该仅对容器接口做出假设,而不是实现。
这只是部分答案,但可以在qazxswpoi上找到STL的详细文档。
以上是关于如何使set :: find()适用于自定义类对象?的主要内容,如果未能解决你的问题,请参考以下文章
adjustsFontForContentSizeCategory 是不是适用于自定义字体?
YOLOv7YOLOv5改进之打印热力图可视化:适用于自定义模型,丰富实验数据
如何将 NSPredicate 应用于自定义 XLForm 行?