Skip to content

Multi set in c++ and oops

An answer to this question on Stack Overflow.

Question

Start with the person class, and create a multiset to hold pointers to person objects. Define the multiset with the comparePersons function object, so it will be sorted automatically by names of persons. Define a half-dozen persons, put them in the multiset, and display its contents. Several of the persons should have the same name, to verify that the multiset stores multiple objects with the same key.

PROBLEM: I am unable to sort the multiset and I am not sure why.

Code: // sorts person objects stored by pointer

#include <iostream>
#include <algorithm>
#include <string>
#include <set> //addded---------------------------------------------
using namespace std;
class person
{
private:
   string lastName;
   string firstName;
   long phoneNumber;
public:
   // default constructor
   person() :lastName("blank"), firstName("blank"), phoneNumber(0L)
   { }
   // 3-arg constructor
   person(string lana, string fina, long pho) :
       lastName(lana), firstName(fina), phoneNumber(pho)
   { }
   friend bool operator<(const person&, const person&);
   friend bool operator==(const person&, const person&);
   void display() const // display person's data
   {
       cout << endl << lastName << ",\t" << firstName
           << "\t\tPhone: " << phoneNumber;
   }
   long get_phone() const // return phone number
   {
       return phoneNumber;
   }
}; //end class person
//--------------------------------------------------------------
// overloaded < for person class
bool operator<(const person& p1, const person& p2)
{
   if (p1.lastName == p2.lastName)
       return (p1.firstName < p2.firstName) ? true : false;
   return (p1.lastName < p2.lastName) ? true : false;
}
//--------------------------------------------------------------
// overloaded == for person class
bool operator==(const person& p1, const person& p2)
{
   return (p1.lastName == p2.lastName &&
       p1.firstName == p2.firstName) ? true : false;
}
//--------------------------------------------------------------
// function object to compare persons using pointers
class comparePersons
{
public:
   bool operator() (const person* ptrP1, const person* ptrP2) const
   {
       return *ptrP1 < *ptrP2;
   }
};
//--------------------------------------------------------------
//function object to display a person, using a pointer
class displayPerson
{
public:
   void operator() (const person* ptrP) const
   {
       ptrP->display();
   }
};
////////////////////////////////////////////////////////////////
int main()
{   
   //make persons
   person* ptrP1 = new person("KuangThu", "Bruce", 4157300);
   person* ptrP2 = new person("Deauville", "William", 8435150);
   person* ptrP3 = new person("Wellington", "John", 9207404);
   person* ptrP4 = new person("Bartoski", "Peter", 6946473);
   person* ptrP5 = new person("Fredericks", "Roger", 7049982);
   person* ptrP6 = new person("McDonald", "Stacey", 7764987);
   person* ptrP7 = new person("KuangThu", "Bruce", 4157300);
   person* ptrP8 = new person("Deauville", "William", 8435150);
   //Creating multiset
   multiset<person*> multiPtrsPers;
   multiPtrsPers.insert(ptrP1);
   multiPtrsPers.insert(ptrP2);
   multiPtrsPers.insert(ptrP3);
   multiPtrsPers.insert(ptrP4);
   multiPtrsPers.insert(ptrP5);
   multiPtrsPers.insert(ptrP6);
   multiPtrsPers.insert(ptrP7);
   multiPtrsPers.insert(ptrP8);
   for_each(multiPtrsPers.begin(),multiPtrsPers.end(), displayPerson());//display person
   cout << endl;
   sort(multiPtrsPers.begin(), multiPtrsPers.end(), comparePersons());//compare persons
   for_each(multiPtrsPers.begin(), multiPtrsPers.end(), displayPerson());//display persons
   cout << endl;
   system("pause");
   return 0;
} end main()

Answer

Sets cannot be sorted because they use an internal ordering in order to quickly locate and insert elements. Sorting the set externally would break this.

Instead, if you refer to the documentation, you find that you can adjust the ordering yourself:

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class multiset;

Which means that what you want is:

std::multiset<person*, comparePersons> multiPtrsPers;