Implicitly deleted member assignment causes a compile error in code that never calls the assignment operator.
#include <vector>
struct A {
A(int arg) : i{ arg } {}
// A& operator=(const A& arg) { return *this; }
const int i;
};
int main()
{
std::vector<A> v;
v.emplace_back(1); // vector of one A initialized to i:1
// The next line causes this compiler error 'A &A::operator =(const A &)': function was implicitly deleted because 'A' has a data member 'A::i' of const - qualified non - class type
v.erase(v.begin()); // ending the lifetime of A and but now using the same storage
v.emplace_back(2); // vector of one A initialized to i:2
}
If I define an assignment operator then the code compiles and, of course, never calls it. Running the code with all special member functions defined shows, as expected, that only the CTOR, and DTOR is called.
So why is this error occurring in multiple compilers?
https://godbolt.org/z/44foEMh6o
CodePudding user response:
Consider how the erase
function might be implemented. It might look something like this:
constexpr iterator erase(iterator pos) {
for (auto i = pos; i 1 != end(); i ) {
*i = move(*(i 1));
}
pop_back();
return pos;
}
(The real parameter type is const_iterator
, but let's ignore this detail.)
If you choose to erase the last element of the vector, then the loop will run zero times and the assignment operator will be invoked zero times. However, you still force the compiler to instantiate the entire body of the erase
function. When this happens, the compiler must perform overload resolution and check whether there is a usable assignment operator. If there is not, a compilation error occurs.
Expecting your program to compile is like expecting this program to compile:
void foo() = delete;
void bar(int num_times) {
while (num_times--) foo();
}
int main() {
bar(0);
}
Would this program compile? Of course not. Even though foo
will never be invoked, the mere fact that you attempt to compile some code that contains a call to foo
will make the program ill-formed.
With a std::vector
, it is possible for you to say "I promise that I will only be removing the last element, so please do not attempt to compile any code that requires the assignment operator". To do this, use the pop_back
function instead of erase
.