在 C++ 中工作的 STL 和 std 自定义比较参数

STL and std custom compare arguments working in c++

我在 Whosebug 上问过这个问题

我了解到我们传递对象,这些对象在其中调用比较运算符并比较我们的值并给出结果。一切顺利。

现在这段代码:

class Compare {
    public:
    bool operator ()(const int &a, const int &b) { return a < b;}
};

void solve(){
    set<int, Compare> s;
    vector<int> arr = {1,4,6,3,7,2,8,588,5};    
    for(int e : arr) s.insert(e);
    for(auto it = s.rbegin();it!=s.rend();it++) cout << *it << ' '; cout << endl;
}

如果我这样做 Compare() 我会出错,这是我认为必须完成的(传递一个对象)。为什么这样?我们如何才能通过比较?

此外,在这段代码中,我无法传递如下函数:

bool comp(const int &a, const int &b) { return a < b; }

void solve(){
    set<int, comp> s;
    vector<int> arr = {1,4,6,3,7,2,8,588,5};    
    for(int e : arr) s.insert(e);
    for(auto it = s.rbegin();it!=s.rend();it++) cout << *it << ' '; cout << endl;
}

这是我所期望的。不传递函数。

现在这段代码:

bool comp(const int &a, const int &b) { return a < b; }

void solve(){
    vector<int> arr = {1,4,6,3,7,2,8,588,5};    
    nth_element(arr.begin(), arr.begin()+3, arr.end(), comp);
    for(int e : arr) cout << e << " "; cout << endl;
}

我可以传递函数并且没有错误。我的意思是发生了什么事?从我的角度来看,我们应该只传递对象,它们会调用它们的 () 重载运算符并比较值,但有时我们传递函数,有时传递对象会出错,​​有时我们只传递 class 名称。 c++ 到底发生了什么

std::set 的第二个模板参数是 类型

您可能会使用函数指针:

bool comp(const int &a, const int &b) { return a < b; }

std::set<int, bool (*)(const int &, const int &)> s(comp);

operator() 必须是常量。那就是 API.

class Compare {
    public:
    bool operator ()(const int &a, const int &b) const { return a < b; }
}

在第一个代码片段中,编译器发出错误,因为您使用对象 Compare() 作为类型模板参数而不是类型 Compare。

如果你会写例如

#include <iostream>
#include <vector>
#include <set>

using namespace std;

class Compare {
    public:
    bool operator ()(const int &a, const int &b) const { return a < b;}
};

int main() 
{
    set<int, Compare> s( ( Compare() ) );
    
    vector<int> arr = {1,4,6,3,7,2,8,588,5};    
    for(int e : arr) s.insert(e);
    for(auto it = s.rbegin();it!=s.rend();it++) cout << *it << ' '; cout << endl;   

    return 0;
}

则程序编译成功,输出为

588 8 7 6 5 4 3 2 1 

作为 class 模板的第二个类型模板参数 std::set 你需要使用类型说明符 Compare。但是如果你想指定构造函数的参数,你需要使用模板参数类型的对象。

第二个代码片段存在同样的问题。你需要像这个演示程序中显示的那样编写。

#include <iostream>
#include <vector>
#include <set>

using namespace std;

bool comp(const int &a, const int &b) { return a < b; }

int main() 
{
    set<int, bool ( * )( const int &, const int & )> s( comp );
    
    vector<int> arr = {1,4,6,3,7,2,8,588,5};    
    for(int e : arr) s.insert(e);
    for(auto it = s.rbegin();it!=s.rend();it++) cout << *it << ' '; cout << endl;   return 0;
}

程序输出同上图

注意class模板std::set声明为

template <class Key, class Compare = less<Key>, 
          class Allocator = allocator<Key> >
class set;

因此,如果您显式指定了第二个模板参数(而不是默认使用函数对象 std::less<Key>),那么您需要在 [=34= 的构造函数中提供此类型的相应对象] 模板 std::set.