如何重载自定义标准::排序比较函数



使用 std::sort 时,如何重载正在使用的自定义比较函数?

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
class Misc {
public:
  // Comment out the next three lines to compile without problems.
  static bool sortPair(const std::pair<int, int> &a, const std::pair<int, int> &b){
    return a.first < b.first;
  }
  static bool sortPair(const std::pair<double, std::string> &a, const std::pair<double, std::string> &b){
    return a.first < b.first;
  }
};
int main () {
  std::vector<std::pair<double, std::string> > u;
  u.push_back(std::make_pair(10.0, "ten"));
  u.push_back(std::make_pair(5.0, "five"));
  u.push_back(std::make_pair(1.0, "one"));
  std::sort(u.begin(), u.end(), Misc::sortPair);
  for (unsigned int i=0; i< u.size(); i++){
    std::cout << u.at(i).first << std::endl;
  }
  return 0;
}

我无法编译它,因为它抱怨:

未解析的重载函数类型

我可以看到使用 sortPair 可能有些模棱两可,但我假设编译器能够根据与向量u关联的类型来解决这个问题。有没有办法指定使用哪个函数/方法来消除问题的歧义?

目前,注释掉第一个sortPair函数允许编译代码并生成正确的排序输出。当然,这是因为它不再模棱两可。

您可以改用函子:

class Misc {
  public:
    // static bool sortPair(const std::pair<int, int> &a, const std::pair<int, int> &b);
    // static bool sortPair(const std::pair<double, std::string> &a, const std::pair<double, std::string> &b);
    bool operator() (const std::pair<int, int> &a, const std::pair<int, int> &b) { // something 
        return true;
    }
    bool operator() (const std::pair<double, std::string> &a, const std::pair<double, std::string> &b) { // something 
        return true;
    }
} misc;
int main()
{
    std::vector<std::pair<double, std::string> > u;
    std::vector<std::pair<int, int> > u2;
    //Fill vector u with data
    std::sort(u.begin(), u.end(), misc);
    std::sort(u2.begin(), u2.end(), misc);
    return 0;
}

由于ustd::pair<double, std::string>的向量,因此您需要调用相应的比较函数。由于仅靠名称是不够的,因此必须通过将其强制转换为具有正确函数指针类型的指针来消除编译器的歧义。在您的情况下,它是一个函数,它接受对类型的两个 const 引用并返回一个布尔值 - 因此您必须转换为的函数指针类型正是:

bool (*)(const std::pair<int, int> &, const std::pair<int, int> &)

合在一起,形成了一个相当丑陋的演员阵容:

std::sort(u.begin(), u.end(), static_cast<bool (*)(const std::pair<int, int> &, const std::pair<int, int> &)>(&Misc::sortPair));

哇。

最好使用一些 typedefs 来阐明你在做什么:

//includes as they were...
typedef std::pair<double, std::string> dsPair; //or something more meaningful
class Misc {
public:
  //Comment out the next three lines to compile without problems
  static bool sortPair(const std::pair<int, int> &a, const std::pair<int, int> &b){
    return a.first < b.first;
  }
  static bool sortPair(dsPair const& a, dsPair const& b){
    return a.first < b.first;
  }
};
int main () {
  std::vector<dsPair> u{ 
    {10.0, "ten"},
    {5.0, "five"},
    {1.0, "one"}
  };
  /** the function pointer typedef
   * It takes a bit getting used to, but no worries, 
   * you won't have to do it THAT often:
   **/
  typedef bool(*dsPairCompFunc)(dsPair const&, dsPair const&); 
  //and now the cast is much clearer:
  std::sort(begin(u), end(u), static_cast<dsPairCompFunc>(&Misc::sortPair));
  for (auto& e : u){
    std::cout << e.first << "n";
  }
  return 0;
}

我将一些旧的 C++03 内容更改为 C++11,以防您的编译器支持它。

从 C++11 开始,您还可以使用 lambda 表达式来定义比较函数。这样,您既不需要Misc类,也不必担心函数消歧:

int main() {
  using dbl_str_pair_t = std::pair<double, std::string>;
  std::vector<dbl_str_pair_t> u {{10.0, "ten"}, {5.0, "five"}, {1.0, "one"}};
  using int_int_pair_t = std::pair<int, int>;
  std::vector<int_int_pair_t> v {{3, 4}, {1, 5}, {2, 6}};
  std::sort(std::begin(u), std::end(u), [](const dbl_str_pair_t& a, const dbl_str_pair_t& b) {
    return a.first < b.first;
  });
  std::sort(std::begin(v), std::end(v), [](const int_int_pair_t& a, const int_int_pair_t& b) {
    return a.first < b.first;
  });
  for (auto const &p : u)
    std::cout << p.first << std::endl;
  for (auto const &p : v)
    std::cout << p.first << std::endl;
  return 0;
}

Ideone上的代码

最新更新