Search code examples
c++classoopvectorconstants

C++: vector.erase instance of a class with const int gives "attempting to reference a deleted function" error C2280


C++: vector.erase instance of a class with const int gives "attempting to reference a deleted function" error C2280

Class B has a const int attribute const_int. If I make a vector of B instances and then delete an element from that vector - I get the following error:

Error   C2280   'B &B::operator =(const B &)': attempting to reference a deleted function   VectorTest  c:\program files (x86)\microsoft visual studio\2017\prof\vc\tools\msvc\14.10.25017\include\xutility 2534    

If I remove the const keyword - the error disappears. How do I fix it while keeping my attribute const_int constant? Why does this error appear, is vector.erase() trying to call some function from class B? Thank you!

B.h

#pragma once
#include <iostream>
#include <vector>
using namespace std;

class B
{
private:
    const int const_int;
public:
    B(int const_int_input);
    ~B();
};

B.cpp

#include "B.h"

B::B(int const_int_input) : const_int(const_int_input)
{
}


B::~B()
{
}

Source.cpp

#include "B.h"

int main() {
    vector<B> test;
    test.push_back(B(1));
    test.erase(test.begin());
    return 0;
}

Solution

  • according to the std::vector::erase documentation:

    Type requirements - T must meet the requirements of MoveAssignable.

    So in order to use std::vector::erase, you need to either have a move-assignment operator ( T& operator = (T&&) ) , or a copy-assignment operator (T& operator = (const T&)). since you supplied your own constructor, the compiler didn't generate any assignment operator.

    The logic behind this requirement is that the vector tries to fill the gap caused by erase by the rest of the variables. it tries to move the elements right to the erased elements in order to fill the hole erase makes.

    Since your class has const int, that means you don't actually want your object to be assigned, because const_int is.. const. you explicitly said you don't want this variable to be re-assigned.

    in this case, you can create an array of pointers to B:

    std::vector<std::unique_ptr<B>> vector;
    vector.emplace_back(std::make_unique<B>(1));
    vector.erase(vector.begin());
    

    another possibility is to lost the const on const_int and provide move-assignment oeprator.