C++结构排序向量中结构元素上的 std::sort 和 std::lower_bound/equal_range 的 lambda
我有一个此结构的 std::vector
:
struct MS
{
double aT;
double bT;
double cT;
};
我想在其上使用 std::sort
以及 std::lower_bound/equal_range
> 等等...
我需要能够对它进行排序并在结构的前两个元素中的任何一个上查找它。所以目前我有这个:
class MSaTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.aT, rhs.aT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.aT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.aT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
class MSbTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.bT, rhs.bT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.bT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.bT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
这允许我使用 MSaTLess() 调用 std::sort
和 std::lower_bound
来基于 aT 元素进行排序/查找并使用 MSbTLess() 根据 bT 元素进行排序/查找。
我想摆脱函子并使用 C++0x lambda 代替。对于相对简单的排序,因为 lambda 将采用两个 MS 类型的对象作为参数。
那么 lower_bound
和其他二分搜索查找算法呢?他们需要能够使用 (MS, double) 参数调用比较器以及相反的 (double, MS),对吧?如何在调用 lower_bound
时最好地为这些提供 lambda?我知道我可以创建一个 MS 虚拟对象,并搜索所需的键值,然后使用与 std::sort 相同的 lambda,但是有没有办法在不使用虚拟对象的情况下做到这一点?
I have a std::vector
of this struct:
struct MS
{
double aT;
double bT;
double cT;
};
which I want to use std::sort
on as well as std::lower_bound/equal_range
etc...
I need to be able to sort it and look it up on either of the first two elements of the struct. So at the moment I have this:
class MSaTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.aT, rhs.aT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.aT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.aT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
class MSbTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.bT, rhs.bT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.bT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.bT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
This allows me to call both std::sort
and std::lower_bound
with MSaTLess() to sort/lookup based on the aT element and with MSbTLess() to sort/lookup based on the bT element.
I'd like to get away from the functors and use C++0x lambdas instead. For sort that is relatively straightforward as the lambda will take two objects of type MS as arguments.
What about for the lower_bound
and other binary search lookup algorithms though? They need to be able to call a comparator with (MS, double) arguments and also the reverse, (double, MS), right? How can I best provide these with a lambda in a call to lower_bound
? I know I could create an MS dummy object with the required key value being searched for and then use the same lambda as with std::sort
but is there a way to do it without using dummy objects?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这有点尴尬,但是如果您检查标准中
lower_bound
和upper_bound
的定义,您会发现lower_bound
的定义取消引用的迭代器作为比较的第一个参数(以及第二个值),而upper_bound
将取消引用的迭代器第二个(以及第一个值) )。所以,我还没有测试过这个,但我想你会想要:
这
非常令人讨厌,并且没有查找更多的东西,我不确定你是否真的有权假设该实现仅在以下情况下使用比较器文本中描述的方式 - 这是结果的定义,而不是达到目标的方法。它对于
binary_search
或equal_range
也没有帮助。25.3.3.1 中没有明确指出迭代器的值类型必须可转换为 T,但算法的要求是 T(在本例中,
double
) 必须是 LessThanComparable,而不是 T 必须以任何特定顺序与迭代器的值类型进行比较。因此,我认为最好始终使用比较两个 MS 结构的 lambda(或函子),而不是传递双精度值作为值,而是传递一个虚拟 MS,并将正确的字段设置为您要查找的值:
如果你不想给 MS 一个构造函数(因为你希望它是 POD),那么你可以编写一个函数来创建你的 MS 对象:
真的,既然有了 lambda,对于这项工作,我们需要一个二分搜索的版本它需要一个一元“比较器”:
但 C++0x 不提供它。
It's a little awkward, but if you check the definitions of
lower_bound
andupper_bound
from the standard, you'll see that the definition oflower_bound
puts the dereferenced iterator as the first parameter of the comparison (and the value second), whereasupper_bound
puts the dereferenced iterator second (and the value first).So, I haven't tested this but I think you'd want:
and
This is pretty nasty, and without looking up a few more things I'm not sure you're actually entitled to assume that the implementation uses the comparator only in the way it's described in the text - that's a definition of the result, not the means to get there. It also doesn't help with
binary_search
orequal_range
.It's not explicitly stated in 25.3.3.1 that the iterator's value type must be convertible to T, but it's sort of implied by the fact that the requirement for the algorithm is that T (in this case,
double
) must be LessThanComparable, not that T must be comparable to the value type of the iterator in any particular order.So I think it's better just to always use a lambda (or functor) that compares two MS structs, and instead of passing a double as a value, pass a dummy MS with the correct field set to the value you're looking for:
If you don't want to give MS a constructor (because you want it to be POD), then you can write a function to create your MS object:
Really, now that there are lambdas, for this job we want a version of binary search that takes a unary "comparator":
C++0x doesn't provide it, though.
算法 std::sort、std::lower_bound 和 std::binary_search 采用比较容器的两个元素的谓词。任何比较两个 MS 对象并在它们按顺序排列时返回 true 的 lambda 应该适用于所有三种算法。
The algorithms std::sort, std::lower_bound, and std::binary_search take a predicate that compares two elements of the container. Any lambda that compares two MS objects and returns
true
when they are in order should work for all three algorithms.与您所说的有关 lambda 的内容没有直接关系,但这可能是使用二分搜索函数的一个想法:
基本上,通过使用
Find
作为值,我们不必提供比较器,因为Find
使用我们指定的字段与MS
进行比较。这与您在这里看到的答案是同一类:如何排序STL 向量,但使用的是值而不是像这种情况下的比较器。不确定它是否很好用,但可能是,因为它指定了要搜索的值以及要在单个短表达式中搜索的字段。Not directly relevant to what you're saying about lambdas, but this might be an idea for using the binary search functions:
Basically, by using
Find
as the value, we don't have to supply a comparator, becauseFind
compares toMS
using the field that we specify. This is the same kind of thing as the answer you saw over here: how to sort STL vector, but using the value rather than the comparator as in that case. Not sure if it'd be all that great to use, but it might be, since it specifies the value to search for and the field to search in a single short expression.我对 std::equal_range 遇到了同样的问题,并提出了替代解决方案。
我有一个指向在类型字段上排序的对象的指针的集合。我需要找到给定类型的对象范围。
尽管它比专用谓词效率低,因为它为我的集合中的每个对象引入了不必要的 nullptr 测试,但它确实提供了一个有趣的替代方案。
顺便说一句,当我像您的示例中那样使用类时,我倾向于执行以下操作。除了更短之外,这还允许我添加其他类型,每个类型仅 1 个函数,而不是每个类型 4 个运算符。
I had the same problem for
std::equal_range
and came up with an alternative solution.I have a collection of pointers to objects sorted on a type field. I need to find the find the range of objects for a given type.
Although it is less efficient than a dedicated predicate as it introduces an unnecessary nullptr test for each object in my collection, it does provide an interesting alternative.
As an aside, when I do use a class as in your example, I tend to do the following. As well as being shorter, this allows me to add additional types with only 1 function per type rather then 4 operators per type.
在 lower_bound 的定义和其他 STL 算法中,Compare 函数使得第一个类型必须与前向迭代器的类型匹配,而第二个类型必须与 T 的类型(即值的类型)匹配。
因此,人们确实可以比较来自不同对象的事物(执行另一种响应称为一元比较器的操作)。在 C++11 中:
这也可以与其他 STL 算法函数一起使用。
In the definition of lower_bound and other STL Algorithms the Compare function is such that the first type must match that of the Forward Iterator and the second type must match that of T (i.e., of the value).
So one indeed can compare things from different objects (doing what the other response called an Unary Comparator). In C++11 :
And this can be used with other STL algorithm functions as well.