Map Insertion Issue

For some reason I am unable to add elements to a map in the below program.

The map should be filled with Nurse objects (as the key) and string vectors as the value.

When I go to add the key list tuple to the map, I get an error message stating:

warning: extended initializer lists only available with -std=c++11 or -std=gnu++11

What does this mean? Am I adding the tuple to the map incorrectly or is my compiler not up to date for c++11 syntax?

I've noted where the problem is with the comment:
/******* Error occuring here ********/

Thanks!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <ostream>
#include <Nurse.h> 
#include <vector>
#include <map>

using namespace std;

int main()
{  
     // Instantiating a map container
     std::map<Nurse, std::vector<std::string> > hospitalList;

     // Instantiating a Nurse object
     Nurse md1("Zeb",2020);
     
     // Instantiating a patient list (of strings).
     std::vector<std::string> md1Patientlist;
     
     // Filling patient list with names
     md1Patientlist.push_back("zoey");
     md1Patientlist.push_back("zander");
     md1Patientlist.push_back("zion");
     
     /******* Error occuring here ********/
     hospitalList.insert({md1,md1Patientlist});
     
    return 0;
}
What compiler, and compiler version are you using? It looks like you're using an older version of whatever compiler you happen to be using. Most of the current compilers are using c++14 by default, older compilers often used c++98 by default.

Have you tried adding the -std flag to your build line (either -std=c++11, -std=c++14, -std=c++17)?
I've enabled c++11 for my compiler and IDE but am now getting this strange error message. Anyone know what the problem is?:

||=== Build: Debug in Object Testing (compiler: GNU GCC Compiler) ===|

|1820|required from 'std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*>

|1873|required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key,

|610|required from 'std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>,

|119|required from here|

|387|error: no match for 'operator<' (operand types are 'const Nurse' and 'const Nurse')|
(x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\stl_pair.h|220|note: candidate: template<class _T1, class _T2> constexpr bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)|

||=== Build failed: 1 error(s), 5 warning(s) (0 minute(s), 1 second(s)) ===|
Looks like you need to implement operator< with the proper const qualifiers.


What version of g++ is your version of MinGW using?

Hello Jlb,

Not sure if im answerinf your question correctly, but this is what I can find in my MinGW file directory:

TDM-GCC Compiler GCC 5 series MinGW 32-bit Edition


Does this answer your question? Please let me know if I am providing the wrong info here!
Well if it is true that it is using GCC 5 you really need to consider updating to a more recent version.

Here is a link to the "current" up to date version, gcc 9.2.0

https://jmeubank.github.io/tdm-gcc/download/

Also unless you're using a 32 bit operating system you should consider using the 64 bit downloads.

Thanks for the advice there, I've updated to GCC 9.2 the 64 bit version. However, the same error message is still being generated.

I think you are correct in that I need to implement the operator function with const qualifiers - but what would this implementation and function signature look like?
Please post your class declaration/definition.

Here are my class header and cpp files below. Thanks!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

#ifndef NURSE_H
#define NURSE_H

#include <string>

class Nurse
{

    private:
        std::string name;
        int id;

    public:
        Nurse();
        Nurse (std::string n);
        Nurse (std::string n, int num);
        //virtual ~Nurse();

        std::string getName();
        void setName(std::string);

        int getID();
        void setID(int num);

        int compare(Nurse doc2);

        // Here is my attempt to declare the operator function.
        Nurse operator()(std::string name1, int id1);

};

#endif // NURSE_H

// Nurse.cpp begins below:

#include "Nurse.h"

using namespace std;


string name;
int id;

Nurse::Nurse()
{
    name = "BLANK NAME";
    id = 99999;
}

Nurse::Nurse(string n)
{
    name = n;
    id = 99999;
}

Nurse::Nurse(string n, int fig)
{
    name = n;
    id = fig;
}

/*~Nurse() {
    //dtor
}*/

string Nurse::getName()
{

    return name;
}

void Nurse::setName(string n)
{

    name = n;
}

int Nurse::getID() 
{

    return id;
}

void Nurse::setID(int fig)
{

    id = fig;
}

int Nurse::compare(Nurse doc2)
{
    if (id > doc2.getID()){

        return 1;
    } else { if (id < doc2.getID()){

            return -1;
        } else {

            return 0;
        }
    }
}

/******* My attempt to implement the operator function. *******/
Nurse Nurse::operator()(string name1, int id1)
{
    Nurse n(name1,id1);
    return n;
}

Well for starters, I don't see any overload for the operator<, a std::map requires this overload if you want to use it as the "key".

By the way why are you defining those global variables in your .cpp file? They don't appear to be needed, but may cause problems later.

Maybe this is what ur trying to do??
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <vector>
#include <map>

class Nurse
{
public:
    std::string name;
    
    Nurse(std::string aName){name = aName;}
    ~Nurse(){}
};

int main()
{
    typedef std::vector<std::string> patient_list;
    std::map<patient_list, Nurse> hospitalList;
    
    Nurse md1("Zeb");
    
    std::vector<std::string> md1Patientlist;
    
    md1Patientlist.push_back("zoey");
    md1Patientlist.push_back("zander");
    md1Patientlist.push_back("zion");
    
    hospitalList.insert({ md1Patientlist, md1});
    
    for(auto i: hospitalList)
    {
        std::cout << "   Nurse: " << i.pair::second.name << '\n';
        std::cout << "Patients:\n";
        for(auto j: i.pair::first)
            std::cout << j << '\n';
    }
    
    return 0;
}



Nurse: Zeb
Patients:
zoey
zander
zion
Program ended with exit code: 0
a std::map uses a binary search tree (bst) to allow for fast insert/delete/find operations on the set of keys
to be able to construct a bst, the elements stored must be comparable (less, greater than)

1
2
3
4
5
6
7
8
9
10
class Nurse{
//...
public:
   bool operator<(const Nurse &b) const; //declaration
};

bool Nurse::operator<(const Nurse &b) const{ //definition
   //true if *this is less than b, false otherwise
   //¿how do you compare nurses?
}
Last edited on
Overloading the operator< function is giving me some trouble here. What arguments should it take? What does it specifically need to do?

Regarding declaring the global variables "name" and "id" in the Nurse.cpp file - I thought that this was an appropriate way to declare the Nurse class's private variables (where the name and id data for each nurse could be stored and then modified / accessed by the implemented getter and setter functions).

Is there a more appropriate way of doing this? How could an instantiation of a class store data if that class didn't have private variables?
What arguments should it take? What does it specifically need to do?

Look as some of the previous posts, they have shown what arguments are required. And it need to "compare" the class to an "external" class (the parameter). Since you're overloading the less than operator you need to decide what makes this class less than the "external" class.


Regarding declaring the global variables "name" and "id" in the Nurse.cpp file - I thought that this was an appropriate way to declare the Nurse class's private variables (where the name and id data for each nurse could be stored and then modified / accessed by the implemented getter and setter functions).


What you're actually doing is declaring two variables totally unrelated to your class, that under certain circumstances will conflict with each other.

You've already declared two variables in the class declaration so these global variables are not needed.

Thank you all. I'm comparing Nurse objects based on their ID, so I also had to declare and implement the getID() function as a const as well (so I could compare *this id with the external Nurse id in the operator function).

I'll have to look more into C++ OOP to understand the correct way to not have those variables exist in the class and be able to have the class without declaring them as global variables.
I'll have to look more into C++ OOP to understand the correct way to not have those variables exist in the class and be able to have the class without declaring them as global variables.


What? Why wouldn't you want have those variables in the class?

Thank you all. I'm comparing Nurse objects based on their ID, so I also had to declare and implement the getID() function as a const as well (so I could compare *this id with the external Nurse id in the operator function).

Well all of your "getters" should probably be declared const, since a getter should not modify the variable. However you should be able to just compare the two ids from the two classes.

Something similar to (where name is a private data member) :
1
2
3
4
        bool operator<(const Nurse& other) const
        {
            return name < other.name;
        }
Perhaps I am misunderstanding your previous comment:


What you're actually doing is declaring two variables totally unrelated to your class, that under certain circumstances will conflict with each other.

You've already declared two variables in the class declaration so these global variables are not needed.


Maybe you are referring to the "name" and "id" variables on the cpp file, yes? Yes, I would like to have these variables in the class but perhaps you are suggesting that I am declaring them twice, or declaring two different "name" and "id" variables altogether (once in the header file and again in the cpp file)?

Is the "name" and "id" declaration in the cpp file incorrect?

If so, then would the setters/getters be able to access the name and id variables on the header file, even though those variables are not declared in the cpp file itself?
Maybe you are referring to the "name" and "id" variables on the cpp file, yes?

Well those are the global variables I'm talking about yes.

Yes, I would like to have these variables in the class

You do have them in the class, see lines 11 and 12 of your code.

but perhaps you are suggesting that I am declaring them twice,

No, you are declaring two different variables named name and id in two different scopes. Once inside your class (the ones you want to keep) and once in the .cpp file (the global variables you want to get rid of).

Is the "name" and "id" declaration in the cpp file incorrect?

Yes, they are incorrect.

If so, then would the setters/getters be able to access the name and id variables on the header file

All class member functions can access all the member variables of the class no matter where the member functions are defined.

Thank you very much!! I see now, this makes sense - thank you for clearing this up. I'm more familiar with writing classes in Java so that could explain my mix up here.
The bottom line - if the key class is complex, unlike my previous, a purpose designed comparator is required. (I'd be surprised if Java isn't the same.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <vector>
#include <map>

class Nurse
{
public:
    std::string name;
    int ID;
    
    Nurse(std::string aName, int aID){ name = aName; ID = aID; }
    ~Nurse(){}
    
    bool operator< (const Nurse &rhs) const
    { return name < rhs.name; }
};

int main()
{
    typedef std::vector<std::string> patient_list;
    std::map<Nurse, patient_list> hospitalList;
    
    Nurse md1("Zeb", 124);
    std::vector<std::string> md1Patientlist;
    md1Patientlist.push_back("zoey");
    md1Patientlist.push_back("zander");
    md1Patientlist.push_back("zion");
    hospitalList[md1] = md1Patientlist;
    
    Nurse md2("Zab", 123);
    std::vector<std::string> md2Patientlist;
    md2Patientlist.push_back("jack");
    md2Patientlist.push_back("jill");
    md2Patientlist.push_back("hope");
    hospitalList[md2] = md2Patientlist;
    
    Nurse md3("Zec", 120);
    std::vector<std::string> md3Patientlist;
    md3Patientlist.push_back("mary");
    md3Patientlist.push_back("bill");
    md3Patientlist.push_back("mabel");
    md3Patientlist.push_back("beulah");
    hospitalList[md3] = md3Patientlist;
    
    for(auto i: hospitalList)
    {
        std::cout << "   Nurse: " << i.first.name << '\n';
        std::cout << "Patients:\n";
        for(auto j: i.second)
            std::cout << j << '\n';
    }
    
    return 0;
}


   Nurse: Zab
Patients:
jack
jill
hope
   Nurse: Zeb
Patients:
zoey
zander
zion
   Nurse: Zec
Patients:
mary
bill
mabel
beulah
Program ended with exit code: 0
Topic archived. No new replies allowed.