Thor Correia
Thor Correia

Reputation: 1309

Can't insert element into vector of a class which contains a reference

I have a class, which has a reference to another struct.

struct DNA { ... };
class Cohort {
    private:
        DNA& genetics;
        ...
    public:
        Cohort(DNA& g) : genetics(g) {}
        ...
};

I then have a vector of Cohorts.

std::vector<Cohort> cohorts;

I must then insert Cohorts at the beginning of the vector.

cohorts.insert(cohorts.begin(), Cohort(eggs, genetics));    

I get an error.

error: object of type 'Thor_Lucas_Development::Cohort' cannot be assigned because its copy assignment
      operator is implicitly deleted

I'm assuming when items are inserted into the vector, it's copied in. Because I have a reference in my Cohorts class, it's copy assignment operator is implicitly deleted.

So... what's going on? I just can't use vectors when dealing with the Cohort class? Or must I new up the Cohort and have pointers to it in the vector?

Kind of annoying.

Upvotes: 0

Views: 175

Answers (2)

bipll
bipll

Reputation: 11940

As the error message says, you cannot rebind a reference in a living object, that is why assignment is deleted by default.

Besides storing pointers in the vector, you can somehow rewrite your class:

I. Use pointers instead of references. They are quite value-like in this usecase:

#include <vector>

struct Nyan {
    int *x;
};

int main() {
    int x;
    std::vector<Nyan> v{{&x}, {&x}, {&x}};
    v.insert(v.begin(), Nyan{&x});
}

(As a replacement for reference, plain pointer is quite OK, but you can use any of the wrappers defined in <memory> should you ever need it.)

You can even add some protection to disallow null pointers:

struct Nyan {
    Nyan(int &x): x(&x) {}
private:
    int *x;
};

II. std::reference_wrapper was introduced in as early as C++11 to accommodate for unrebindability, to allow to store references in containers:

#include <vector>
#include <functional>

struct Nyan {
    std::reference_wrapper<int> x;
};

int main() {
    int x;
    std::vector<Nyan> v{{x}, {x}, {x}};
    v.insert(v.begin(), Nyan{x});
}

Upvotes: 0

molbdnilo
molbdnilo

Reputation: 66371

You can construct the object in place:

cohorts.emplace(cohorts.begin(), eggs, genetics); 

But reference members are rarely a good idea – use a pointer instead.
And if you insert at the beginning a lot, you probably want std::deque rather than std::vector.

Upvotes: 1

Related Questions