C ++中`std :: sort`比较器的不同类型

时间:2018-10-25 08:42:45

标签: c++

当我们为std::sort提供比较器功能时,我们使用以下重载:

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

其中std::sort的比较器函数应具有以下语法:

bool cmp(const Type1 &a, const Type2 &b);

但是您可以看到ab可能具有不同的类型。 cppreference说:

  

类型Type1Type2必须使得类型RandomIt的对象   可以取消引用,然后隐式转换为两者。

但是当我尝试对单个数组进行排序时,我仍然无法完全理解如何在一个数组中拥有两种不同类型。

有人可以为std::sort的比较器功能提供一个不同类型的小例子吗?

6 个答案:

答案 0 :(得分:20)

这与数组中存储的内容无关,只能存储一种类型。关于比较器功能是什么。例如:

struct Animal {};
struct Cat : Animal {};
struct Dog : Animal {};
struct Hound : Dog {};

bool cmp(const Animal &a, const Animal &b);

即使您有DogCatHound的列表,您仍然可以使用函数cmp对它们进行排序,因为它们都是隐式可转换的。即。

std::vector<Hound> hounds;
... // fill hounds
std::sort(hounds.begin(), hounds.end(), cmp);

您甚至可以想象Type1Type2不相同的情况,例如:

bool cmp(const Animal &a, const Dog &b);
etc ...

尽管这种情况非常罕见。

  

类型1 (动物)和类型2 (狗)的类型必须使得RandomIt (猎犬)类型的对象可以被取消引用然后隐式转换为两者。 。

要点是,对cmp函数可以采用的类型的限制不包括一般性。在某些情况下,这是一个好主意,但在这种情况下,它会过分严格,可能会给边缘案例实现带来问题。此外,cmp中使用的std::sort函数受Compare提出的要求的约束(可能是为了简化)。 比较要求用于其他各种事物,例如std::max

答案 1 :(得分:13)

  

但是我仍然无法确切地知道尝试对它进行排序时如何在一个数组中拥有2种不同类型。

数组中不能有两种不同的类型。比较器并不建议有可能。之所以这样指定,仅仅是因为:

  1. 当类型不同时,代码 的格式可以正确。
  2. 要求相同类型是一种限制,几乎没有作用。

因此,该规范提供的合同比“显而易见”的合同更宽松,以帮助我们的代码在需要时更加灵活。作为一个玩具示例,假设我们有这个比较器:

auto cmp(int a, long b) -> bool { return a < b; }

为什么阻止我们使用此完全合法的(尽管很愚蠢的)函数对整数数组进行排序?

答案 2 :(得分:7)

  

但是我仍然无法确切地知道尝试对它进行排序时如何在一个数组中拥有2种不同类型。

你不能。

但是 Compare 的要求不仅是对数组进行排序,还是对所有数组进行排序!

在任何时候您都想将一件事与另一件事进行比较。

webpack.mix.js小于minutes(42)吗?是!在这种情况下,您可能会发现比较器很有用。

比较是一个更通用的概念,可以在整个语言中找到用途。

  

有人可能会为std :: sort的比较器函数提供一个具有不同类型的小示例

其他人显示了一些示例,这些示例指示您必须多么愚蠢地找到针对“ hours(1)”使用的“有用”示例。

但这不是“ std :: sort的比较器函数”。这是 a 比较器函数,您恰好与std::sort一起使用。

的确,这样做时,您可能希望选择特定的比较器来接受相同类型的操作数。

答案 3 :(得分:4)

  

但是我仍然无法确切知道如何在单个数组中拥有2种不同类型

在一个数组中不能有两种不同的类型。

一个数组只能有单一类型的对象。但是,该单一类型必须可以隐式转换为cmp的两种参数类型。

  

有人可能会为std :: sort的比较器功能提供一个具有不同类型的小示例吗?

您在这里:

int arr[] = {1, 2, 3, 0};
auto cmp = [](const int &a, const long &b) {
    return a < b;
};
std::sort(std::begin(arr), std::end(arr), cmp);

请注意cmp的两个不同参数。这只是一个最小的例子,从技术上讲是正确的,但公认是荒谬的。坦白说,我从未遇到过这样的情况:对于比较函数的参数使用不同的类型会很有用。

答案 4 :(得分:4)

比较器的要求比您想象的要宽松得多:

  1. 它必须在序列中接受两个解引用的迭代器作为参数。
    使用隐式转换顺序就可以了。
  2. 返回值必须在上下文中可转换为bool
    一个显式的转换运算符可以正常工作。
  3. 它必须是可复制且不可破坏的完整类型。
  4. 不得修改参数,以免干扰调用算法。
    如果完全使用引用,则丝毫不暗示使用常量引用。
  5. 它必须引起完全弱阶(cmp(a,b)暗示!cmp(b,a),cmp(a,b)&& cmp(b,c)暗示cmp(a,c))。
  6. li>

因此,有效但相当无用的比较器将是:

template <class... X>
auto useless(X&&...) { return nullptr; }

答案 5 :(得分:1)

Compare上的类型要求不是要对要排序的序列元素说太多,而是允许所有comp

if (comp(*first, *other))

有效。

大部分时间Type1等于Type2,但不要求它们相等