0

I have a set of a custom class and when I'm trying to insert an object of that class, the terminal gives me an error:

#ifndef EMPLOYEE_HH
#define EMPLOYEE_HH

#include <string>
#include <iostream>
#include <set>
#include <iterator>
using namespace std ;

class Employee {

public:
  // Constructor
  Employee(const char* name, double salary) : _name(name), _salary(salary) {}

  // Accessors
  const char* name() const { return _name.c_str() ; }
  double salary() const { return _salary ; }

  // Print functions
  void businessCard(ostream& os = cout) const {
    os << "   +------------------+  " << endl
       << "   | ACME Corporation |  " << endl 
       << "   +------------------+  " << endl
       << "   " << name() << endl ;
  }
  
private:

  string _name ;
  double _salary ;
} ;

class Manager : public Employee{
  public:
  
  Manager(const char* name, double salary) : Employee(name, salary) {};

  void addSubordinate(Employee& empl){
    _subs.insert(empl);
  }

  const set<Employee*>& listOfSubordinates() const{
    return _subs;  
  }

  void businessCard() const{
    Employee::businessCard();
    
    set <Employee*>::iterator it=_subs.begin();
    cout <<"Managed employees: " <<endl;
    while(it!=_subs.end()){
      cout <<*it++ <<endl;
    }
  }
  private:
  set <Employee*> _subs;
};

#endif

The addSubordinate() routine:

void addSubordinate(Employee& empl){
        _subs.insert(empl);
      }

returns this error:

no instance of overloaded function "std::set<_Key, _Compare, _Alloc>::insert [with _Key=Employee *, _Compare=std::less<Employee *>, _Alloc=std::allocator<Employee *>]" matches the argument list

I have tried to overload the operator < as other people suggested in response to similar questions, but that doesn't seem to solve the issue.

Kemosabe
  • 15
  • 3
  • You have a `set`, i.e. each element is a pointer to `Employee`. So you cannot insert `Employee& empl` with `_subs.insert(empl);`. You could use `_subs.insert(&empl);` if you are 100% the pointer will not become dangling. A better approach would be to use e.g. `std::map>`. – wohlstad Aug 21 '22 at 17:01
  • I have tried that and it effectively works; the only problem comes when I need to print the employees. It just outputs the memory address of the object Employee. – Kemosabe Aug 21 '22 at 17:06
  • "It just outputs the reference to the employees" Do you mean that the pointers themselves are printed? That's because you're printing the actual pointers and not the `Employee` objects they point to. Assuming you have a valid `operator<<` for output of `Employee` objects, you need to *dereference* the pointers to get the objects they point to. – Some programmer dude Aug 21 '22 at 17:09
  • However, since you're not dealing with polymorphic types and probably don't want to make a manager a subordinate of another manager (in this exercise) then you should change the set to be a set of `Employee` *objects*, not pointers to them. So `std::set` instead. – Some programmer dude Aug 21 '22 at 17:11
  • Also, [`using namespace std;` is a bad habit](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). Doing it in a header file is doubly as bad. – Some programmer dude Aug 21 '22 at 17:12
  • Thank you for your feedback Some programmer dude; I am using `std::set` only because my professor says to do so in the exercise. Same with `using namespace std;` but I will fix that. Moreover, I am not sure how to dereference, since I am using the iterator to go through the set. – Kemosabe Aug 21 '22 at 17:17
  • @AndreaRusso -- Your `Employee` class lacks a virtual destructor, thus it is not safe to be used in a polymorphic fashion. – PaulMcKenzie Aug 21 '22 at 17:17
  • @AndreaRusso *I am using std::set only because my professor says to do so in the exercise.* -- You are using `std::set`, not `std::set`. It was recommended you change that to `std::set`. The second thing is that we don't listen to professors or teachers -- StackOverflow volunteers, and especially the ones with high reputation, listen to experience they've had with the language. If you want to get answers geared to experienced users, that is what you will get. We also have no idea what your professor says is ok, so the answers are what they are. – PaulMcKenzie Aug 21 '22 at 17:20
  • @PaulMckenzie, sorry I misspelled, of course I meant to say `std::set`. I gladly accept your advices. – Kemosabe Aug 21 '22 at 17:26
  • Figured out the dereferencing bit, thanks to everybody. – Kemosabe Aug 21 '22 at 17:35

2 Answers2

1

Your set accepts a pointer to an Employee, but you are trying to insert the object itself.

What you can do is

void addSubordinate(Employee& empl){
    _subs.insert(&empl); // This will store the address to the object
  }

or accept a pointer itself

void addSubordinate(Employee* empl){
    _subs.insert(empl);
  }
VanSHOE
  • 26
  • 2
0

You need to define the < operator in the Employee class. The items in a set are always sorted and since you don't have a comparator it won't let you insert an instance of that class. Try something like this:

bool operator<(const Employee& emp){
    return salary() < emp.salary();
}