如何实现自定义模板排序功能

How can I implement a custom template sort function?

本文关键字:排序 功能 自定义 何实现 实现      更新时间:2023-10-16

我有一个对向量,我希望它仅按键稳定排序(可能会多次发生)。我不为此使用multimap,因为它不是显式稳定的。因此,我提供了一个自定义比较函数来stable_sort。我现在正在努力模板化这个函数。下面是一个简短的测试实现,向您展示用例:

#include <iostream>
#include <algorithm>
#include <vector>
#include "test.h"
using namespace std;
int main() {
  typedef pair<int, int> TPair;
  vector<TPair> data(10);
  data[0] = make_pair(7, 1); 
  data[1] = make_pair(3, 2); 
  data[2] = make_pair(8, 0); 
  data[3] = make_pair(5, 1); 
  data[4] = make_pair(3, 1); 
  data[5] = make_pair(2, 0); 
  data[6] = make_pair(7, 0); 
  data[7] = make_pair(6, 0); 
  data[8] = make_pair(5, 0); 
  data[9] = make_pair(3, 0); 
  stable_sort(data.begin(), data.end(), comp1);
  for (unsigned int i = 0; i < 10; ++i) {
    cout << data[i].first << "t" << data[i].second << endl;
  }
  return 0;
}

提供的分拣功能可在test.h

#include <vector>
#ifndef TEST_H_
#define TEST_H_
using namespace std;
bool comp1(pair<int, int> const & a, pair<int, int> const & b) {
  return a.first < b.first;
}
template <typename TElemA, typename TElemB>
bool comp2(pair<TElemA, TElemB> const & a, pair<TElemA, TElemB> const & b) {
  return a.first < b.first;
}
template <typename TPair>
bool comp3(TPair const & a, TPair const & b) {
  return a.first < b.first;
}
#endif
  • comp1运作良好,没什么可抱怨的。首先,我尝试模板化这对的元素:
  • comp2不起作用:test.cpp:25:3: error: no matching function for call to 'stable_sort'.
  • comp3失败,并显示与 comp2 相同的错误消息。

这个模板函数有什么问题?

stable_sort本身就是一个模板,它的第三个参数的类型是一个模板参数。这意味着您不能将函数模板作为参数传递,因为模板参数推导在这里不适用 - 没有什么可以告诉你要追求哪个实例化。因此,您必须显式指定模板参数:

stable_sort(data.begin(), data.end(), comp2<int, int>);

但是,如果您为此提供一个函子,您会更好:

struct comp2
{
  template <typename TElemA, typename TElemB>
  bool operator() (pair<TElemA, TElemB> const & a, pair<TElemA, TElemB> const & b) const {
    return a.first < b.first;
  }
};
stable_sort(data.begin(), data.end(), comp2());

这样,实际的模板参数推导将推迟到已知所需类型的时间。

从 C++14 开始,您还可以使用 lambda 表达式而不是使用模板。这是因为 C++14 允许泛型 lambda,其函数参数可以使用 auto 类型说明符声明:

std::stable_sort(std::begin(data), std::end(data), [](auto const &a, auto const &b){
    return a.first < b.first;
});

这样,您的代码变得相当短,但仍然适用于任何可比较的std::pair键。

Ideone上的代码