使用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
函数允许编译代码并生成正确的排序输出。当然,这是因为它不再含糊不清。
答案 0 :(得分:4)
您可以改为使用仿函数:
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;
}
答案 1 :(得分:1)
由于u
是std::pair<double, std::string>
的向量,因此您需要调用相应的比较函数。由于仅仅名称是不够的,因此必须通过将其转换为具有正确函数指针类型的指针来为编译器消除歧义。在你的情况下,它是一个函数,它对对类型采用两个const引用并返回一个bool - 所以你必须转换为的函数指针类型就是:
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));
哇。
最好使用一些typedef来澄清你在做什么:
//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,以防你的编译器支持它。
答案 2 :(得分:0)
自C++11起,您也可以使用lambda expressions代替定义比较功能。这样,您既不需要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;
}