在代码审查期间,我的一个同事正在使用结构对std :: set进行排序。我还是C ++的新手,必须自己实现它才能完全理解它。可悲的是,我有些挣扎,因为在实现结构的operator()之后,MSVC也迫使我实现operator <。
有人可以解释一下为什么如果我使用结构对std :: set进行排序的话,为什么必须同时实现两个运算符?我猜测不需要operator <,因为std :: set调用了一些基本的比较功能?
class Hallo {
int one;
int two;
public:
Hallo(int one, int two);
bool operator < (const Hallo& rhs) const
{
return one < rhs.GetOne();
}
struct cmpStruct{
bool operator()(Hallo const &lhs, Hallo const &rhs) const
{
return lhs.GetOne() < rhs.GetOne();
}
int main(int ac, char* av[]){
const Hallo a{ 1, 1 };
const Hallo b{ 2, 2 };
const Hallo c{ 3, 3 };
const Hallo d{ 5, 5 };
std::set<Hallo, Hallo::cmpStruct> sortedList{};
std::set<Hallo> unsortedList{};
sortedList.insert(b);
sortedList.insert(c);
sortedList.insert(a);
sortedList.insert(d);
unsortedList.insert(b);
unsortedList.insert(c);
unsortedList.insert(a);
unsortedList.insert(d);
答案 0 :(得分:2)
默认情况下,$enrollment = $user->enrollments()
->where('course_id', $course->id)
->first();
// If $enrollment is NULL, they don't belong to this Course
dd($enrollment->completed);
使用std::set
比较两个operator <
实例。这就是为什么您需要定义一个Hallo
函数进行比较的原因。没有用于比较operator<
的默认操作。
编辑1:指定排序或比较功能
struct
构造函数之一允许您指定一个用于比较std::set
实例的函数。如果您不想向结构添加重载的Hallo
方法,则需要将比较两个operator<
实例的函数传递给Hallo
构造函数。同样,std::set
或struct
实例没有默认的比较运算符;您必须创建一些东西。
编辑2:比较功能的目的
class
的比较函数参数允许您为std::set
结构指定比较函数。它允许您创建一个按成员Hallo
订购的商品,也可以创建另一个按one
成员订购的商品。
此外,您可以定义升序或降序的排序功能。选择很丰富。
答案 1 :(得分:2)
有人可以解释一下为什么如果我使用结构对std :: set进行排序的话,为什么必须同时使用两个运算符?
因为您创建了两个{"_module": "oauth2client.client",
"scopes": ["https://www.googleapis.com/auth/spreadsheets"],
"token_expiry": "2019-01-10T20:32:28Z",
"id_token": null,
"user_agent": "ResponseRates",
"access_token": FIRST_STRING_OF_CHARACTERS,
"token_uri": "https://accounts.google.com/o/oauth2/token",
"invalid": false,
"token_response": {
"access_token": FIRST_STRING_OF_CHARACTERS,
"scope": "https://www.googleapis.com/auth/spreadsheets",
"expires_in": 3600,
"token_type": "Bearer"},
"client_id": SECOND_STRING_OF_CHARACTERS.apps.googleusercontent.com",
"token_info_uri": "https://www.googleapis.com/oauth2/v3/tokeninfo",
"client_secret": THIRD_STRING_OF_CHARACTORS,
"revoke_uri": "https://accounts.google.com/o/oauth2/revoke",
"_class": "OAuth2Credentials",
"refresh_token": FOURTH_STRING_OF_CHARACTORS,
"id_token_jwt": null
}
实例,并以std::set
作为键,并且在第一个实例中您明确地将class Hallo
用作函子,但是在第二个实例中却隐式地使用了{{1} },如Apples docs on InAppPurchases
cmpStruct
和std::less
使用“一些基本比较功能”,即template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;
this discussion:
用于执行比较的功能对象。除非专门,否则会在类型T上调用操作符<< / strong>。
重点是我的。因此,除非您将std::less
专用于operator<
或不将std::less
实例化中的class Hallo
替换为其他内容,否则将需要std::less
作为方法或独立函数。 / p>
答案 2 :(得分:0)
任何数学集合的成员都是唯一的;没有两个可以拥有相同的密钥。但是,对于struct
这样的用户定义类型,相同是什么意思?我们知道两个字符串相等或两个整数意味着什么。但是,对您的结构而言,“相同”的含义取决于您,也取决于您定义。
std::set
的成员根据定义既是唯一的又是排序的。因此,除了强制唯一性之外,std::set
依次表示成员。什么顺序?同样,对于用户定义的类型,由用户决定一个对象“小于”另一个对象的含义。
这就是operator<
出现的地方。您定义一个对象小于另一个对象的含义。 std::set
以用户定义的类型调用用户定义的运算符,并按定义的顺序放置成员。它还使用该函数来实现唯一性:如果无法在现有项之前或之后插入新项,则该新项等于该项,并且拒绝插入。