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?
You can't. Your type violates the "Assignable" requirement for standard containers.
ISO/IEC 14882:2003 23.1 [lib.container.requirements] / 3:
From table 64 (
Assignable
requirements):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 likevector::operator=
andvector::assign
might be significantly more efficient.A
vector
often needs to move elements around. Every time a vector needs to grow when you callpush_back()
it reallocates memory to keep itself contiguous, and copies all the existing elements into the new space. Also if you callinsert()
orremove()
elements must be shifted. Forvector
to be able to do all that the elements must be copy-assignable, which means that the type you store in the vector must have the assignment operator defined.Generally, if you define a class, the compiler will generate the assignment operator for that class for you. However, there are cases when the compiler is unable to do that. One of these cases is when the class has constant members (note that pointers-to-const are ok).
So, in your case, the problem is the
const string name
. It prevents the compiler from generatingoperator=()
, which in turn preventsvector
from compiling, even though you do not actually use assignment on its elements yourself.One solution is to make
name
non-const. The other is to write your ownStudent::operator=()
, in some way that makes sense. The third way is, as you have pointed out, to use a vector of pointers rather than a vector of objects. But then you have to handle their allocation and de-allocation.P.S. The other case when the compiler cannot generate
operator=
is when your class has members that are references.Elements of vectors must be copy-assignable, which your
Student
struct isn't because of theconst
member. Simply usestring name
instead ofconst string name
. Unless you have a specific requirement, constant members in classes are seldom useful. If you want to prevent changes to the member, make it private and add a public getter function.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 thatstd::vector
provides need to make assignments, and therefore require a (public) copy-assignment operator.Your options are:
name
non-const
.const
member.