Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vector of structs with const members?

Let's say I have

#include <string>
#include <vector>
using namespace std;

struct Student
{
    const string name;
    int grade;
    Student(const string &name) : name(name) { }
};

How do I, then, keep a vector of students?

int main()
{
    vector<Student> v;

    // error C2582: 'operator =' function is unavailable in 'Student'
    v.push_back(Student("john"));
}

Is there even a way to do this, or must I allocate all the students on the heap, and store a pointer to each of them instead?

like image 649
user541686 Avatar asked Dec 11 '11 22:12

user541686


People also ask

Can struct members be const?

You can const individual members of a struct. Declaring an entire instance of a struct with a const qualifier is the same as creating a special-purpose copy of the struct with all members specified as const .

Can I have a vector of structs?

You can actually create a vector of structs!

Can vectors be const?

If we desire that the elements of a vector should not be modified, we can declare that vector as a const vector. However, we must initialize this vector when it is declared, as it is not possible to modify it subsequently. Thus, a const vector can be declared and initialized as shown below.

Can you add to a const vector?

You can't put items into a const vector, the vectors state is the items it holds, and adding items to the vector modifies that state. If you want to append to a vector you must take in a non const ref.


2 Answers

You can't. Your type violates the "Assignable" requirement for standard containers.

ISO/IEC 14882:2003 23.1 [lib.container.requirements] / 3:

The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.

From table 64 (Assignable requirements):

In Table 64, T is the type used to instantiate the container, t is a value of T, and u is a value of (possibly const) T.

expression: t = u; return type: T; post-condition: t is equivalent to u

In theory, a std::vector equivalent could choose to do destruction and copy construction in all cases, but that's not the contract that has been chosen. If reallocation isn't required, then using the contained type's assignment operator for things like vector::operator= and vector::assign might be significantly more efficient.

like image 185
CB Bailey Avatar answered Oct 02 '22 08:10

CB Bailey


The simple answer is: you can't. If you have const member variables, then the compiler can't supply a default copy-assignment operator. However, many of the operations that std::vector provides need to make assignments, and therefore require a (public) copy-assignment operator.

Your options are:

  1. Make name non-const.
  2. Write your own copy-assignment operator, and think of a way to deal with "copying" a const member.
like image 40
Oliver Charlesworth Avatar answered Oct 02 '22 07:10

Oliver Charlesworth