How to implement less-than comparison operator (<)

Question | Mar 11, 2017 | rparekh 

It is very common for C++ applications to overload or to define the comparison operators ( e.g., <, >, and == ) on user-defined data types. For instance, a key of user-defined type in associative containers (e.g., std::map) usually has a comparison function implemented as overloaded less-than (<) or greater-than (>) operator:

struct Key {
 // overloaded less-than operator
 bool operator < (const Key& rhs) const;
};
// default comparison function is std::less<Key>
std::map<Key, std::string> container;

Another use case, which is discussed here, of an overloaded comparison operator is when the elements of a sequence container (e.g., std::vector) need to be sorted. Let's take the example of a struct CourseGrade that is used to record a student's grade in a particular course:

// an enum of grades: A B C D
enum Grade : uint8_t { D = 1, C, B, A };

// CourseGrade is for Grade of a Course
struct CourseGrade {
 Grade grade;
 std::string courseName;

 // Need to be implemented  
 bool operator < ( const CourseGrade& rhs ) {
   // ----- ?? ----
 }
};

The CourseGrade has an overloaded less-than (<) operator for comparing and sorting the CourseGrade records (objects). A std::vector container of CourseGrade objects is defined and initialized as:

std::vector<CourseGrade> cgs = {
    { C, "Physics" },
    { A, "History of America" },
    { C, "Mathematics" },
    { A, "Political Economics" },
    { B, "Probability and Statistics" }
};

The container - cgs - is sorted by using std::sort that requires a comparison function of type bool cmp(const Type& a, const Type& b). We pass a lambda as the comparison function object which invokes the overloaded CourseGrade::operator<() on its CourseGrade parameters as follows:

std::sort(cgs.begin(), cgs.end(), 
  [](const CourseGrade& lhs, const CourseGrade& rhs) {
     // calls lhs.operator<(rhs);
     return lhs < rhs;
});

The CourseGrade::operator<() is implemented in a way such that the cgs elements are first sorted by grades, and within the same grade by course-name in ascending order. Therefore once sorted, cgs contains CourseGrade objects in the following order:

 /*  C, "Mathematics"
     C, "Physics"
     B, "Probability and Statistics"
     A, "History of America"
     A, "Political Economics" */

Select the correct implementation of less-than-operator (<) on CourseGrade that would result in the sorted collection as shown above. ( All the choices below are using std::string::compare, which returns an integer that is -ve, 0, or +ve depending on if a std::string is less than, equal, or greater than the passed std::string ).