Timothy Wong
Timothy Wong

Reputation: 709

Two types of value in one vector C++

Say I have a vector for class Students, but the requirement of the question states that I cannot put grade together in the constructor, so I will have to work around it.

Is it possible that I have two values in one vector slot?

For example, the class Student and string grade are my arguments.

vector<Student*, string> Students;

So, at the end of the day, if I cout the vector, I should get Student AND the grade in one slot.

Does this work? If so, how do I push_back the value?

Otherwise, is there another way to do this?

Upvotes: 7

Views: 23537

Answers (3)

Drop
Drop

Reputation: 13005

There are multiple ways of achieving this.

A. Array of structures:

A1. Composition:

class GradedStudent {
    Student body;
    string grade;
    public:
    GradedStudent(const string& grade);
    // reimplement all methods of `Student`, 
    // delegating implementations to `body`
};

std::vector<GradedStudent> gradedStudents;

A2. Inheritance (all students have grades):

class Student {
public:
    Student();
};

class GradedStudent {
    string grade;
public:
    GradedStudent(const string& grade);
};

std::vector<GradedStudent*> gradedStudents;

A3. Inheritance + polymorphysm (some students have grades and some don`t):

class Student {
public:
    Student();
    virtual ~Student();
    virtual const string& getGrade() const { return ""; }
};

class GradedStudent : public IStudent {
    string grade;
public:
    GradedStudent(const string& grade);
    virtual string getGrade() const override { return grade; }
};

std::vector<Student*> students;
// non graded students will have empty string as a grade

B. Structure of Arrays approach (separate array for grades):

std::vector<Student*> students;
std::vector<string> grades;

for(int i = 0; i < students.size(); ++i) {
    auto* student = students[i];
    auto grade = grades[i];
}

C. Associative container (doesn`t honor "use std::vector" requirement):

std::map<Student*, string> students;

for(auto student : students) {
    auto* student = student.first;
    auto grade = student.second;
}

Those are classic ones. There might be more.

If all students have grades, you should really make grade a member of this class.

P.S. Do you really need to store pointers in a vector (as opposed to storing objects)?

Upvotes: 2

Humam Helfawi
Humam Helfawi

Reputation: 20264

std::vector<std::pair<Student*, string>> students;

or even better:

std::map<Student*, string> students;

Pushing values:

first case:

students.push_back(std::make_pair(x,y));

even better(as @snps advised):

students.emplace_back(x, y);

second case:

students[x]=y;

Be aware that in the second case you can not add multiple record with the same Student* value. If you try it will write over the old one.

Upvotes: 13

Tarik Neaj
Tarik Neaj

Reputation: 548

You can use std::map for this.

http://www.cplusplus.com/reference/map/map/

Upvotes: 1

Related Questions